forked from recloudstream/cloudstream
		
	mainApi changes
This commit is contained in:
		
							parent
							
								
									117730e9a8
								
							
						
					
					
						commit
						94561e0d5b
					
				
					 19 changed files with 358 additions and 325 deletions
				
			
		|  | @ -111,6 +111,12 @@ object APIHolder { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     var apis: List<MainAPI> = arrayListOf() |     var apis: List<MainAPI> = arrayListOf() | ||||||
|  |     private var apiMap: Map<String, Int>? = null | ||||||
|  | 
 | ||||||
|  |     private fun initMap() { | ||||||
|  |         if (apiMap == null) | ||||||
|  |             apiMap = apis.mapIndexed { index, api -> api.name to index }.toMap() | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     fun getApiFromName(apiName: String?): MainAPI { |     fun getApiFromName(apiName: String?): MainAPI { | ||||||
|         return getApiFromNameNull(apiName) ?: apis[defProvider] |         return getApiFromNameNull(apiName) ?: apis[defProvider] | ||||||
|  | @ -118,11 +124,9 @@ object APIHolder { | ||||||
| 
 | 
 | ||||||
|     fun getApiFromNameNull(apiName: String?): MainAPI? { |     fun getApiFromNameNull(apiName: String?): MainAPI? { | ||||||
|         if (apiName == null) return null |         if (apiName == null) return null | ||||||
|         for (api in allProviders) { |         initMap() | ||||||
|             if (apiName == api.name) | 
 | ||||||
|                 return api |         return apiMap?.get(apiName)?.let { apis.getOrNull(it) } | ||||||
|         } |  | ||||||
|         return null |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun getApiFromUrlNull(url: String?): MainAPI? { |     fun getApiFromUrlNull(url: String?): MainAPI? { | ||||||
|  | @ -622,10 +626,65 @@ interface SearchResponse { | ||||||
|     val apiName: String |     val apiName: String | ||||||
|     var type: TvType? |     var type: TvType? | ||||||
|     var posterUrl: String? |     var posterUrl: String? | ||||||
|  |     var posterHeaders: Map<String, String>? | ||||||
|     var id: Int? |     var id: Int? | ||||||
|     var quality: SearchQuality? |     var quality: SearchQuality? | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fun MainAPI.newMovieSearchResponse( | ||||||
|  |     name: String, | ||||||
|  |     url: String, | ||||||
|  |     type: TvType = TvType.Movie, | ||||||
|  |     fix: Boolean = true, | ||||||
|  |     initializer: MovieSearchResponse.() -> Unit = { }, | ||||||
|  | ): MovieSearchResponse { | ||||||
|  |     val builder = MovieSearchResponse(name, if (fix) fixUrl(url) else url, this.name, type) | ||||||
|  |     builder.initializer() | ||||||
|  | 
 | ||||||
|  |     return builder | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fun MainAPI.newTvSeriesSearchResponse( | ||||||
|  |     name: String, | ||||||
|  |     url: String, | ||||||
|  |     type: TvType = TvType.TvSeries, | ||||||
|  |     fix: Boolean = true, | ||||||
|  |     initializer: TvSeriesSearchResponse.() -> Unit = { }, | ||||||
|  | ): TvSeriesSearchResponse { | ||||||
|  |     val builder = TvSeriesSearchResponse(name, if (fix) fixUrl(url) else url, this.name, type) | ||||||
|  |     builder.initializer() | ||||||
|  | 
 | ||||||
|  |     return builder | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | fun MainAPI.newAnimeSearchResponse( | ||||||
|  |     name: String, | ||||||
|  |     url: String, | ||||||
|  |     type: TvType = TvType.Anime, | ||||||
|  |     fix: Boolean = true, | ||||||
|  |     initializer: AnimeSearchResponse.() -> Unit = { }, | ||||||
|  | ): AnimeSearchResponse { | ||||||
|  |     val builder = AnimeSearchResponse(name, if (fix) fixUrl(url) else url, this.name, type) | ||||||
|  |     builder.initializer() | ||||||
|  | 
 | ||||||
|  |     return builder | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fun SearchResponse.addQuality(quality: String) { | ||||||
|  |     this.quality = getQualityFromString(quality) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fun SearchResponse.addPoster(url: String?, headers: Map<String, String>? = null) { | ||||||
|  |     this.posterUrl = url | ||||||
|  |     this.posterHeaders = headers | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fun LoadResponse.addPoster(url: String?, headers: Map<String, String>? = null) { | ||||||
|  |     this.posterUrl = url | ||||||
|  |     this.posterHeaders = headers | ||||||
|  | } | ||||||
|  | 
 | ||||||
| enum class ActorRole { | enum class ActorRole { | ||||||
|     Main, |     Main, | ||||||
|     Supporting, |     Supporting, | ||||||
|  | @ -648,19 +707,62 @@ data class AnimeSearchResponse( | ||||||
|     override val name: String, |     override val name: String, | ||||||
|     override val url: String, |     override val url: String, | ||||||
|     override val apiName: String, |     override val apiName: String, | ||||||
|     override var type: TvType?, |     override var type: TvType? = null, | ||||||
| 
 | 
 | ||||||
|     override var posterUrl: String?, |     override var posterUrl: String? = null, | ||||||
|     val year: Int? = null, |     var year: Int? = null, | ||||||
|     val dubStatus: EnumSet<DubStatus>? = null, |     var dubStatus: EnumSet<DubStatus>? = null, | ||||||
|  | 
 | ||||||
|  |     var otherName: String? = null, | ||||||
|  |     var episodes: MutableMap<DubStatus, Int> = mutableMapOf(), | ||||||
| 
 | 
 | ||||||
|     val otherName: String? = null, |  | ||||||
|     val dubEpisodes: Int? = null, |  | ||||||
|     val subEpisodes: Int? = null, |  | ||||||
|     override var id: Int? = null, |     override var id: Int? = null, | ||||||
|     override var quality: SearchQuality? = null, |     override var quality: SearchQuality? = null, | ||||||
|  |     override var posterHeaders: Map<String, String>? = null, | ||||||
| ) : SearchResponse | ) : SearchResponse | ||||||
| 
 | 
 | ||||||
|  | fun AnimeSearchResponse.addDubStatus(status: DubStatus, episodes: Int? = null) { | ||||||
|  |     this.dubStatus = dubStatus?.also { it.add(status) } ?: EnumSet.of(status) | ||||||
|  |     if (this.type?.isMovieType() != true) | ||||||
|  |         if (episodes != null && episodes > 0) | ||||||
|  |             this.episodes[status] = episodes | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fun AnimeSearchResponse.addDubStatus(isDub: Boolean, episodes: Int? = null) { | ||||||
|  |     addDubStatus(if (isDub) DubStatus.Dubbed else DubStatus.Subbed, episodes) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fun AnimeSearchResponse.addDub(episodes: Int?) { | ||||||
|  |     if(episodes == null || episodes <= 0) return | ||||||
|  |     addDubStatus(DubStatus.Dubbed, episodes) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fun AnimeSearchResponse.addSub(episodes: Int?) { | ||||||
|  |     if(episodes == null || episodes <= 0) return | ||||||
|  |     addDubStatus(DubStatus.Subbed, episodes) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fun AnimeSearchResponse.addDubStatus( | ||||||
|  |     dubExist: Boolean, | ||||||
|  |     subExist: Boolean, | ||||||
|  |     dubEpisodes: Int? = null, | ||||||
|  |     subEpisodes: Int? = null | ||||||
|  | ) { | ||||||
|  |     if (dubExist) | ||||||
|  |         addDubStatus(DubStatus.Dubbed, dubEpisodes) | ||||||
|  | 
 | ||||||
|  |     if (subExist) | ||||||
|  |         addDubStatus(DubStatus.Subbed, subEpisodes) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fun AnimeSearchResponse.addDubStatus(status: String, episodes: Int? = null) { | ||||||
|  |     if (status.contains("(dub)", ignoreCase = true)) { | ||||||
|  |         addDubStatus(DubStatus.Dubbed) | ||||||
|  |     } else if (status.contains("(sub)", ignoreCase = true)) { | ||||||
|  |         addDubStatus(DubStatus.Subbed) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| data class TorrentSearchResponse( | data class TorrentSearchResponse( | ||||||
|     override val name: String, |     override val name: String, | ||||||
|     override val url: String, |     override val url: String, | ||||||
|  | @ -670,31 +772,34 @@ data class TorrentSearchResponse( | ||||||
|     override var posterUrl: String?, |     override var posterUrl: String?, | ||||||
|     override var id: Int? = null, |     override var id: Int? = null, | ||||||
|     override var quality: SearchQuality? = null, |     override var quality: SearchQuality? = null, | ||||||
|  |     override var posterHeaders: Map<String, String>? = null, | ||||||
| ) : SearchResponse | ) : SearchResponse | ||||||
| 
 | 
 | ||||||
| data class MovieSearchResponse( | data class MovieSearchResponse( | ||||||
|     override val name: String, |     override val name: String, | ||||||
|     override val url: String, |     override val url: String, | ||||||
|     override val apiName: String, |     override val apiName: String, | ||||||
|     override var type: TvType?, |     override var type: TvType? = null, | ||||||
| 
 | 
 | ||||||
|     override var posterUrl: String?, |     override var posterUrl: String? = null, | ||||||
|     val year: Int? = null, |     val year: Int? = null, | ||||||
|     override var id: Int? = null, |     override var id: Int? = null, | ||||||
|     override var quality: SearchQuality? = null, |     override var quality: SearchQuality? = null, | ||||||
|  |     override var posterHeaders: Map<String, String>? = null, | ||||||
| ) : SearchResponse | ) : SearchResponse | ||||||
| 
 | 
 | ||||||
| data class TvSeriesSearchResponse( | data class TvSeriesSearchResponse( | ||||||
|     override val name: String, |     override val name: String, | ||||||
|     override val url: String, |     override val url: String, | ||||||
|     override val apiName: String, |     override val apiName: String, | ||||||
|     override var type: TvType?, |     override var type: TvType? = null, | ||||||
| 
 | 
 | ||||||
|     override var posterUrl: String?, |     override var posterUrl: String? = null, | ||||||
|     val year: Int?, |     val year: Int? = null, | ||||||
|     val episodes: Int?, |     val episodes: Int? = null, | ||||||
|     override var id: Int? = null, |     override var id: Int? = null, | ||||||
|     override var quality: SearchQuality? = null, |     override var quality: SearchQuality? = null, | ||||||
|  |     override var posterHeaders: Map<String, String>? = null, | ||||||
| ) : SearchResponse | ) : SearchResponse | ||||||
| 
 | 
 | ||||||
| interface LoadResponse { | interface LoadResponse { | ||||||
|  | @ -713,6 +818,7 @@ interface LoadResponse { | ||||||
|     var actors: List<ActorData>? |     var actors: List<ActorData>? | ||||||
|     var comingSoon: Boolean |     var comingSoon: Boolean | ||||||
|     var syncData: MutableMap<String, String> |     var syncData: MutableMap<String, String> | ||||||
|  |     var posterHeaders: Map<String, String>? | ||||||
| 
 | 
 | ||||||
|     companion object { |     companion object { | ||||||
|         private val malIdPrefix = malApi.idPrefix |         private val malIdPrefix = malApi.idPrefix | ||||||
|  | @ -844,6 +950,7 @@ data class TorrentLoadResponse( | ||||||
|     override var actors: List<ActorData>? = null, |     override var actors: List<ActorData>? = null, | ||||||
|     override var comingSoon: Boolean = false, |     override var comingSoon: Boolean = false, | ||||||
|     override var syncData: MutableMap<String, String> = mutableMapOf(), |     override var syncData: MutableMap<String, String> = mutableMapOf(), | ||||||
|  |     override var posterHeaders: Map<String, String>? = null, | ||||||
| ) : LoadResponse | ) : LoadResponse | ||||||
| 
 | 
 | ||||||
| data class AnimeLoadResponse( | data class AnimeLoadResponse( | ||||||
|  | @ -871,6 +978,7 @@ data class AnimeLoadResponse( | ||||||
|     override var actors: List<ActorData>? = null, |     override var actors: List<ActorData>? = null, | ||||||
|     override var comingSoon: Boolean = false, |     override var comingSoon: Boolean = false, | ||||||
|     override var syncData: MutableMap<String, String> = mutableMapOf(), |     override var syncData: MutableMap<String, String> = mutableMapOf(), | ||||||
|  |     override var posterHeaders: Map<String, String>? = null, | ||||||
| ) : LoadResponse | ) : LoadResponse | ||||||
| 
 | 
 | ||||||
| fun AnimeLoadResponse.addEpisodes(status: DubStatus, episodes: List<Episode>?) { | fun AnimeLoadResponse.addEpisodes(status: DubStatus, episodes: List<Episode>?) { | ||||||
|  | @ -882,7 +990,7 @@ fun MainAPI.newAnimeLoadResponse( | ||||||
|     name: String, |     name: String, | ||||||
|     url: String, |     url: String, | ||||||
|     type: TvType, |     type: TvType, | ||||||
|     comingSoonIfNone: Boolean, |     comingSoonIfNone: Boolean = true, | ||||||
|     initializer: AnimeLoadResponse.() -> Unit = { }, |     initializer: AnimeLoadResponse.() -> Unit = { }, | ||||||
| ): AnimeLoadResponse { | ): AnimeLoadResponse { | ||||||
|     val builder = AnimeLoadResponse(name = name, url = url, apiName = this.name, type = type) |     val builder = AnimeLoadResponse(name = name, url = url, apiName = this.name, type = type) | ||||||
|  | @ -898,15 +1006,6 @@ fun MainAPI.newAnimeLoadResponse( | ||||||
|     return builder |     return builder | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fun MainAPI.newAnimeLoadResponse( |  | ||||||
|     name: String, |  | ||||||
|     url: String, |  | ||||||
|     type: TvType, |  | ||||||
|     initializer: AnimeLoadResponse.() -> Unit = { }, |  | ||||||
| ): AnimeLoadResponse { |  | ||||||
|     return newAnimeLoadResponse(name, url, type, true, initializer) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| data class MovieLoadResponse( | data class MovieLoadResponse( | ||||||
|     override var name: String, |     override var name: String, | ||||||
|     override var url: String, |     override var url: String, | ||||||
|  | @ -926,6 +1025,7 @@ data class MovieLoadResponse( | ||||||
|     override var actors: List<ActorData>? = null, |     override var actors: List<ActorData>? = null, | ||||||
|     override var comingSoon: Boolean = false, |     override var comingSoon: Boolean = false, | ||||||
|     override var syncData: MutableMap<String, String> = mutableMapOf(), |     override var syncData: MutableMap<String, String> = mutableMapOf(), | ||||||
|  |     override var posterHeaders: Map<String, String>? = null, | ||||||
| ) : LoadResponse | ) : LoadResponse | ||||||
| 
 | 
 | ||||||
| fun <T> MainAPI.newMovieLoadResponse( | fun <T> MainAPI.newMovieLoadResponse( | ||||||
|  | @ -1046,6 +1146,7 @@ data class TvSeriesLoadResponse( | ||||||
|     override var actors: List<ActorData>? = null, |     override var actors: List<ActorData>? = null, | ||||||
|     override var comingSoon: Boolean = false, |     override var comingSoon: Boolean = false, | ||||||
|     override var syncData: MutableMap<String, String> = mutableMapOf(), |     override var syncData: MutableMap<String, String> = mutableMapOf(), | ||||||
|  |     override var posterHeaders: Map<String, String>? = null, | ||||||
| ) : LoadResponse | ) : LoadResponse | ||||||
| 
 | 
 | ||||||
| fun MainAPI.newTvSeriesLoadResponse( | fun MainAPI.newTvSeriesLoadResponse( | ||||||
|  |  | ||||||
|  | @ -14,7 +14,6 @@ import org.mozilla.javascript.Context | ||||||
| import org.mozilla.javascript.Scriptable | import org.mozilla.javascript.Scriptable | ||||||
| import java.net.URI | import java.net.URI | ||||||
| import java.net.URLDecoder | import java.net.URLDecoder | ||||||
| import java.util.* |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class AllAnimeProvider : MainAPI() { | class AllAnimeProvider : MainAPI() { | ||||||
|  | @ -88,49 +87,48 @@ class AllAnimeProvider : MainAPI() { | ||||||
|         @JsonProperty("data") val data: Data |         @JsonProperty("data") val data: Data | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     data class RandomMain ( |     data class RandomMain( | ||||||
|         @JsonProperty("data" ) var data : DataRan? = DataRan() |         @JsonProperty("data") var data: DataRan? = DataRan() | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     data class DataRan ( |     data class DataRan( | ||||||
|         @JsonProperty("queryRandomRecommendation" ) var queryRandomRecommendation : ArrayList<QueryRandomRecommendation> = arrayListOf() |         @JsonProperty("queryRandomRecommendation") var queryRandomRecommendation: ArrayList<QueryRandomRecommendation> = arrayListOf() | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     data class QueryRandomRecommendation ( |     data class QueryRandomRecommendation( | ||||||
|         @JsonProperty("_id"               ) val Id                : String? = null, |         @JsonProperty("_id") val Id: String? = null, | ||||||
|         @JsonProperty("name"              ) val name              : String? = null, |         @JsonProperty("name") val name: String? = null, | ||||||
|         @JsonProperty("englishName"       ) val englishName       : String? = null, |         @JsonProperty("englishName") val englishName: String? = null, | ||||||
|         @JsonProperty("nativeName"        ) val nativeName        : String? = null, |         @JsonProperty("nativeName") val nativeName: String? = null, | ||||||
|         @JsonProperty("thumbnail"         ) val thumbnail         : String? = null, |         @JsonProperty("thumbnail") val thumbnail: String? = null, | ||||||
|         @JsonProperty("airedStart"        ) val airedStart        : String? = null, |         @JsonProperty("airedStart") val airedStart: String? = null, | ||||||
|         @JsonProperty("availableChapters" ) val availableChapters : String? = null, |         @JsonProperty("availableChapters") val availableChapters: String? = null, | ||||||
|         @JsonProperty("availableEpisodes" ) val availableEpisodes : String? = null, |         @JsonProperty("availableEpisodes") val availableEpisodes: String? = null, | ||||||
|         @JsonProperty("__typename"        ) val _typename         : String? = null |         @JsonProperty("__typename") val _typename: String? = null | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     override suspend fun getMainPage(): HomePageResponse { |     override suspend fun getMainPage(): HomePageResponse { | ||||||
|         val items = ArrayList<HomePageList>() |         val items = ArrayList<HomePageList>() | ||||||
|         val urls = listOf( |         val urls = listOf( | ||||||
|             Pair("Top Anime", |             Pair( | ||||||
|                 "$mainUrl/graphql?variables=%7B%22search%22%3A%7B%22allowAdult%22%3Afalse%2C%22sortBy%22%3A%22Top%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"), |                 "Top Anime", | ||||||
|             Pair("Animes", |                 "$mainUrl/graphql?variables=%7B%22search%22%3A%7B%22allowAdult%22%3Afalse%2C%22sortBy%22%3A%22Top%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" | ||||||
|                 "$mainUrl/graphql?variables=%7B%22search%22%3A%7B%22allowAdult%22%3Afalse%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"), |             ), | ||||||
|  |             Pair( | ||||||
|  |                 "Animes", | ||||||
|  |                 "$mainUrl/graphql?variables=%7B%22search%22%3A%7B%22allowAdult%22%3Afalse%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 random = "$mainUrl/graphql?variables=%7B%22format%22%3A%22anime%22%7D&extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%2221ac672633498a3698e8f6a93ce6c2b3722b29a216dcca93363bf012c360cd54%22%7D%7D" |         val random = | ||||||
|  |             "$mainUrl/graphql?variables=%7B%22format%22%3A%22anime%22%7D&extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%2221ac672633498a3698e8f6a93ce6c2b3722b29a216dcca93363bf012c360cd54%22%7D%7D" | ||||||
|         val ranlink = app.get(random).text |         val ranlink = app.get(random).text | ||||||
|         val jsonran = parseJson<RandomMain>(ranlink) |         val jsonran = parseJson<RandomMain>(ranlink) | ||||||
|         val ranhome = jsonran.data?.queryRandomRecommendation?.map { |         val ranhome = jsonran.data?.queryRandomRecommendation?.map { | ||||||
|             AnimeSearchResponse( |             newAnimeSearchResponse(it.name!!,"$mainUrl/anime/${it.Id}", fix = false) { | ||||||
|                 it.name!!, |                 this.posterUrl = it.thumbnail | ||||||
|                 "$mainUrl/anime/${it.Id}", |                 this.otherName = it.nativeName | ||||||
|                 this.name, |             } | ||||||
|                 TvType.Anime, |  | ||||||
|                 it.thumbnail, |  | ||||||
|                 null, |  | ||||||
|                 EnumSet.of(DubStatus.Subbed, DubStatus.Dubbed), |  | ||||||
|                 it.nativeName, |  | ||||||
|             ) |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         items.add(HomePageList("Random", ranhome!!)) |         items.add(HomePageList("Random", ranhome!!)) | ||||||
|  | @ -144,18 +142,14 @@ class AllAnimeProvider : MainAPI() { | ||||||
|                 !(it.availableEpisodes?.raw == 0 && it.availableEpisodes.sub == 0 && it.availableEpisodes.dub == 0) |                 !(it.availableEpisodes?.raw == 0 && it.availableEpisodes.sub == 0 && it.availableEpisodes.dub == 0) | ||||||
|             } |             } | ||||||
|             results.map { |             results.map { | ||||||
|                 home.add(AnimeSearchResponse( |                 home.add( | ||||||
|                     it.name, |                     newAnimeSearchResponse(it.name, "$mainUrl/anime/${it.Id}", fix = false) { | ||||||
|                     "$mainUrl/anime/${it.Id}", |                         this.posterUrl = it.thumbnail | ||||||
|                     this.name, |                         this.year = it.airedStart?.year | ||||||
|                     TvType.Anime, |                         this.otherName = it.englishName | ||||||
|                     it.thumbnail, |                         addDub(it.availableEpisodes?.dub) | ||||||
|                     it.airedStart?.year, |                         addSub(it.availableEpisodes?.sub) | ||||||
|                     EnumSet.of(DubStatus.Subbed, DubStatus.Dubbed), |                     }) | ||||||
|                     it.englishName, |  | ||||||
|                     it.availableEpisodes?.dub, |  | ||||||
|                     it.availableEpisodes?.sub |  | ||||||
|                 )) |  | ||||||
|             } |             } | ||||||
|             items.add(HomePageList(HomeName, home)) |             items.add(HomePageList(HomeName, home)) | ||||||
|         } |         } | ||||||
|  | @ -180,18 +174,13 @@ class AllAnimeProvider : MainAPI() { | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return results.map { |         return results.map { | ||||||
|             AnimeSearchResponse( |             newAnimeSearchResponse(it.name, "$mainUrl/anime/${it.Id}", fix = false) { | ||||||
|                 it.name, |                 this.posterUrl = it.thumbnail | ||||||
|                 "$mainUrl/anime/${it.Id}", |                 this.year = it.airedStart?.year | ||||||
|                 this.name, |                 this.otherName = it.englishName | ||||||
|                 TvType.Anime, |                 addDub(it.availableEpisodes?.dub) | ||||||
|                 it.thumbnail, |                 addSub(it.availableEpisodes?.sub) | ||||||
|                 it.airedStart?.year, |             } | ||||||
|                 EnumSet.of(DubStatus.Subbed, DubStatus.Dubbed), |  | ||||||
|                 it.englishName, |  | ||||||
|                 it.availableEpisodes?.dub, |  | ||||||
|                 it.availableEpisodes?.sub |  | ||||||
|             ) |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -12,7 +12,6 @@ import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
| import com.lagradost.cloudstream3.utils.JsUnpacker | import com.lagradost.cloudstream3.utils.JsUnpacker | ||||||
| import com.lagradost.cloudstream3.utils.getQualityFromName | import com.lagradost.cloudstream3.utils.getQualityFromName | ||||||
| import org.jsoup.Jsoup | import org.jsoup.Jsoup | ||||||
| import java.util.* |  | ||||||
| import kotlin.math.pow | import kotlin.math.pow | ||||||
| 
 | 
 | ||||||
| class AnimePaheProvider : MainAPI() { | class AnimePaheProvider : MainAPI() { | ||||||
|  | @ -84,19 +83,14 @@ class AnimePaheProvider : MainAPI() { | ||||||
|             try { |             try { | ||||||
|                 val response = app.get(i.first).text |                 val response = app.get(i.first).text | ||||||
|                 val episodes = mapper.readValue<AnimePaheLatestReleases>(response).data.map { |                 val episodes = mapper.readValue<AnimePaheLatestReleases>(response).data.map { | ||||||
| 
 |                     newAnimeSearchResponse( | ||||||
|                     AnimeSearchResponse( |  | ||||||
|                         it.animeTitle, |                         it.animeTitle, | ||||||
|                         "https://pahe.win/a/${it.animeId}?slug=${it.animeTitle}", |                         "https://pahe.win/a/${it.animeId}?slug=${it.animeTitle}", | ||||||
|                         this.name, |                         fix = false | ||||||
|                         TvType.Anime, |                     ) { | ||||||
|                         it.snapshot, |                         this.posterUrl = it.snapshot | ||||||
|                         null, |                         addDubStatus(DubStatus.Subbed, it.episode) | ||||||
|                         EnumSet.of(DubStatus.Subbed), |                     } | ||||||
|                         null, |  | ||||||
|                         null, |  | ||||||
|                         it.episode |  | ||||||
|                     ) |  | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 items.add(HomePageList(i.second, episodes)) |                 items.add(HomePageList(i.second, episodes)) | ||||||
|  | @ -151,18 +145,14 @@ class AnimePaheProvider : MainAPI() { | ||||||
|         val data = req.let { mapper.readValue<AnimePaheSearch>(it) } |         val data = req.let { mapper.readValue<AnimePaheSearch>(it) } | ||||||
| 
 | 
 | ||||||
|         return data.data.map { |         return data.data.map { | ||||||
|             AnimeSearchResponse( |             newAnimeSearchResponse( | ||||||
|                 it.title, |                 it.title, | ||||||
|                 "https://pahe.win/a/${it.id}?slug=${it.title}", |                 "https://pahe.win/a/${it.id}?slug=${it.title}", | ||||||
|                 this.name, |                 fix = false | ||||||
|                 TvType.Anime, |             ) { | ||||||
|                 it.poster, |                 this.posterUrl = it.poster | ||||||
|                 it.year, |                 addDubStatus(DubStatus.Subbed, it.episodes) | ||||||
|                 EnumSet.of(DubStatus.Subbed), |             } | ||||||
|                 null, |  | ||||||
|                 null, |  | ||||||
|                 it.episodes |  | ||||||
|             ) |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -189,7 +179,6 @@ class AnimePaheProvider : MainAPI() { | ||||||
|         @JsonProperty("data") val data: List<AnimeData> |         @JsonProperty("data") val data: List<AnimeData> | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     private suspend fun generateListOfEpisodes(link: String): ArrayList<Episode> { |     private suspend fun generateListOfEpisodes(link: String): ArrayList<Episode> { | ||||||
|         try { |         try { | ||||||
|             val attrs = link.split('/') |             val attrs = link.split('/') | ||||||
|  |  | ||||||
|  | @ -9,7 +9,6 @@ import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
| import com.lagradost.cloudstream3.utils.Qualities | import com.lagradost.cloudstream3.utils.Qualities | ||||||
| import org.json.JSONObject | import org.json.JSONObject | ||||||
| import org.jsoup.nodes.Element | import org.jsoup.nodes.Element | ||||||
| import java.util.* |  | ||||||
| 
 | 
 | ||||||
| class AnimeWorldProvider : MainAPI() { | class AnimeWorldProvider : MainAPI() { | ||||||
|     override var mainUrl = "https://www.animeworld.tv" |     override var mainUrl = "https://www.animeworld.tv" | ||||||
|  | @ -31,6 +30,7 @@ class AnimeWorldProvider : MainAPI() { | ||||||
|                 else -> TvType.Anime |                 else -> TvType.Anime | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|         fun getStatus(t: String?): ShowStatus? { |         fun getStatus(t: String?): ShowStatus? { | ||||||
|             return when (t?.lowercase()) { |             return when (t?.lowercase()) { | ||||||
|                 "finito" -> ShowStatus.Completed |                 "finito" -> ShowStatus.Completed | ||||||
|  | @ -54,25 +54,20 @@ class AnimeWorldProvider : MainAPI() { | ||||||
| 
 | 
 | ||||||
|         val statusElement = this.select("div.status") // .first() |         val statusElement = this.select("div.status") // .first() | ||||||
|         val dub = statusElement.select(".dub").isNotEmpty() |         val dub = statusElement.select(".dub").isNotEmpty() | ||||||
|         val dubStatus = if (dub) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(DubStatus.Subbed) | 
 | ||||||
|         val episode = statusElement.select(".ep").text().split(' ').last().toIntOrNull() |         val episode = if (showEpisode) statusElement.select(".ep").text().split(' ').last() | ||||||
|  |             .toIntOrNull() else null | ||||||
|         val type = when { |         val type = when { | ||||||
|             statusElement.select(".movie").isNotEmpty() -> TvType.AnimeMovie |             statusElement.select(".movie").isNotEmpty() -> TvType.AnimeMovie | ||||||
|             statusElement.select(".ova").isNotEmpty() -> TvType.OVA |             statusElement.select(".ova").isNotEmpty() -> TvType.OVA | ||||||
|             else -> TvType.Anime |             else -> TvType.Anime | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return AnimeSearchResponse( |         return newAnimeSearchResponse(title, url, type) { | ||||||
|             title, |             addDubStatus(dub, episode) | ||||||
|             url, |             this.otherName = otherTitle | ||||||
|             name, |             this.posterUrl = poster | ||||||
|             type, |         } | ||||||
|             poster, |  | ||||||
|             dubStatus = dubStatus, |  | ||||||
|             otherName = if (otherTitle != title) otherTitle else null, |  | ||||||
|             dubEpisodes = if (showEpisode && type != TvType.AnimeMovie && dub) episode else null, |  | ||||||
|             subEpisodes = if (showEpisode && type != TvType.AnimeMovie && !dub) episode else null |  | ||||||
|         ) |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override suspend fun getMainPage(): HomePageResponse { |     override suspend fun getMainPage(): HomePageResponse { | ||||||
|  | @ -113,14 +108,17 @@ class AnimeWorldProvider : MainAPI() { | ||||||
|                 arr[0].split(' ')[0].toIntOrNull() |                 arr[0].split(' ')[0].toIntOrNull() | ||||||
|             else |             else | ||||||
|                 arr[1].split(' ')[0].toIntOrNull()?.let { |                 arr[1].split(' ')[0].toIntOrNull()?.let { | ||||||
|                     arr[0].removeSuffix("h").toIntOrNull()?.times(60)!!.plus(it) } |                     arr[0].removeSuffix("h").toIntOrNull()?.times(60)!!.plus(it) | ||||||
|                 } |                 } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         val document = app.get(url).document |         val document = app.get(url).document | ||||||
| 
 | 
 | ||||||
|         val widget = document.select("div.widget.info") |         val widget = document.select("div.widget.info") | ||||||
|         val title = widget.select(".info .title").text().removeSuffix(" (ITA)") |         val title = widget.select(".info .title").text().removeSuffix(" (ITA)") | ||||||
|         val otherTitle = widget.select(".info .title").attr("data-jtitle").removeSuffix(" (ITA)") |         val otherTitle = widget.select(".info .title").attr("data-jtitle").removeSuffix(" (ITA)") | ||||||
|         val description = widget.select(".desc .long").first()?.text() ?: widget.select(".desc").text() |         val description = | ||||||
|  |             widget.select(".desc .long").first()?.text() ?: widget.select(".desc").text() | ||||||
|         val poster = document.select(".thumb img").attr("src") |         val poster = document.select(".thumb img").attr("src") | ||||||
| 
 | 
 | ||||||
|         val type: TvType = getType(widget.select("dd").first()?.text()) |         val type: TvType = getType(widget.select("dd").first()?.text()) | ||||||
|  |  | ||||||
|  | @ -2,8 +2,9 @@ package com.lagradost.cloudstream3.animeproviders | ||||||
| 
 | 
 | ||||||
| import com.fasterxml.jackson.annotation.JsonProperty | import com.fasterxml.jackson.annotation.JsonProperty | ||||||
| import com.lagradost.cloudstream3.* | import com.lagradost.cloudstream3.* | ||||||
| import com.lagradost.cloudstream3.utils.* |  | ||||||
| import com.lagradost.cloudstream3.utils.AppUtils.parseJson | import com.lagradost.cloudstream3.utils.AppUtils.parseJson | ||||||
|  | import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
|  | import com.lagradost.cloudstream3.utils.loadExtractor | ||||||
| import java.util.* | import java.util.* | ||||||
| 
 | 
 | ||||||
| class AnimeflvnetProvider:MainAPI() { | class AnimeflvnetProvider:MainAPI() { | ||||||
|  | @ -13,6 +14,11 @@ class AnimeflvnetProvider:MainAPI() { | ||||||
|             else if (t.contains("Película")) TvType.AnimeMovie |             else if (t.contains("Película")) TvType.AnimeMovie | ||||||
|             else TvType.Anime |             else TvType.Anime | ||||||
|         } |         } | ||||||
|  |         fun getDubStatus(title: String): DubStatus { | ||||||
|  |             return if (title.contains("Latino") || title.contains("Castellano")) | ||||||
|  |                 DubStatus.Dubbed | ||||||
|  |             else DubStatus.Subbed | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|     override var mainUrl = "https://www3.animeflv.net" |     override var mainUrl = "https://www3.animeflv.net" | ||||||
|     override var name = "Animeflv.net" |     override var name = "Animeflv.net" | ||||||
|  | @ -43,19 +49,10 @@ class AnimeflvnetProvider:MainAPI() { | ||||||
|                     val url = it.selectFirst("a").attr("href").replace(epRegex,"") |                     val url = it.selectFirst("a").attr("href").replace(epRegex,"") | ||||||
|                         .replace("ver/","anime/") |                         .replace("ver/","anime/") | ||||||
|                     val epNum = it.selectFirst("span.Capi").text().replace("Episodio ","").toIntOrNull() |                     val epNum = it.selectFirst("span.Capi").text().replace("Episodio ","").toIntOrNull() | ||||||
|                     AnimeSearchResponse( |                     newAnimeSearchResponse(title, url) { | ||||||
|                         title, |                         this.posterUrl = fixUrl(poster) | ||||||
|                         fixUrl(url), |                         addDubStatus(getDubStatus(title), epNum) | ||||||
|                         this.name, |                     } | ||||||
|                         TvType.Anime, |  | ||||||
|                         fixUrl(poster), |  | ||||||
|                         null, |  | ||||||
|                         if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of( |  | ||||||
|                             DubStatus.Dubbed |  | ||||||
|                         ) else EnumSet.of(DubStatus.Subbed), |  | ||||||
|                         subEpisodes = epNum, |  | ||||||
|                         dubEpisodes = epNum, |  | ||||||
|                     ) |  | ||||||
|                 }) |                 }) | ||||||
|         ) |         ) | ||||||
|         for ((url, name) in urls) { |         for ((url, name) in urls) { | ||||||
|  | @ -64,15 +61,10 @@ class AnimeflvnetProvider:MainAPI() { | ||||||
|                 val home = doc.select("ul.ListAnimes li article").map { |                 val home = doc.select("ul.ListAnimes li article").map { | ||||||
|                     val title = it.selectFirst("h3.Title").text() |                     val title = it.selectFirst("h3.Title").text() | ||||||
|                     val poster = it.selectFirst("figure img").attr("src") |                     val poster = it.selectFirst("figure img").attr("src") | ||||||
|                     AnimeSearchResponse( |                     newAnimeSearchResponse(title, fixUrl(it.selectFirst("a").attr("href"))) { | ||||||
|                         title, |                         this.posterUrl = fixUrl(poster) | ||||||
|                         fixUrl(it.selectFirst("a").attr("href")), |                         addDubStatus(MonoschinosProvider.getDubStatus(title)) | ||||||
|                         this.name, |                     } | ||||||
|                         TvType.Anime, |  | ||||||
|                         fixUrl(poster), |  | ||||||
|                         null, |  | ||||||
|                         if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(DubStatus.Subbed), |  | ||||||
|                     ) |  | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 items.add(HomePageList(name, home)) |                 items.add(HomePageList(name, home)) | ||||||
|  |  | ||||||
|  | @ -201,20 +201,10 @@ class GogoanimeProvider : MainAPI() { | ||||||
|                 items.add(HomePageList(i.second, (parseRegex.findAll(html.text).map { |                 items.add(HomePageList(i.second, (parseRegex.findAll(html.text).map { | ||||||
|                     val (link, epNum, title, poster) = it.destructured |                     val (link, epNum, title, poster) = it.destructured | ||||||
|                     val isSub = listOf(1, 3).contains(i.first.toInt()) |                     val isSub = listOf(1, 3).contains(i.first.toInt()) | ||||||
|                     AnimeSearchResponse( |                     newAnimeSearchResponse(title, link) { | ||||||
|                         title, |                         this.posterUrl = poster | ||||||
|                         link, |                         addDubStatus(!isSub, epNum.toIntOrNull()) | ||||||
|                         this.name, |                     } | ||||||
|                         TvType.Anime, |  | ||||||
|                         poster, |  | ||||||
|                         null, |  | ||||||
|                         if (isSub) EnumSet.of(DubStatus.Subbed) else EnumSet.of( |  | ||||||
|                             DubStatus.Dubbed |  | ||||||
|                         ), |  | ||||||
|                         null, |  | ||||||
|                         if (!isSub) epNum.toIntOrNull() else null, |  | ||||||
|                         if (isSub) epNum.toIntOrNull() else null, |  | ||||||
|                     ) |  | ||||||
|                 }).toList())) |                 }).toList())) | ||||||
|             } catch (e: Exception) { |             } catch (e: Exception) { | ||||||
|                 e.printStackTrace() |                 e.printStackTrace() | ||||||
|  |  | ||||||
|  | @ -14,6 +14,12 @@ class MonoschinosProvider : MainAPI() { | ||||||
|             else if (t.contains("Pelicula")) TvType.AnimeMovie |             else if (t.contains("Pelicula")) TvType.AnimeMovie | ||||||
|             else TvType.Anime |             else TvType.Anime | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         fun getDubStatus(title: String): DubStatus { | ||||||
|  |             return if (title.contains("Latino") || title.contains("Castellano")) | ||||||
|  |                 DubStatus.Dubbed | ||||||
|  |             else DubStatus.Subbed | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override var mainUrl = "https://monoschinos2.com" |     override var mainUrl = "https://monoschinos2.com" | ||||||
|  | @ -50,19 +56,10 @@ class MonoschinosProvider : MainAPI() { | ||||||
|                     val url = it.selectFirst("a").attr("href").replace("ver/", "anime/") |                     val url = it.selectFirst("a").attr("href").replace("ver/", "anime/") | ||||||
|                         .replace(epRegex, "sub-espanol") |                         .replace(epRegex, "sub-espanol") | ||||||
|                     val epNum = it.selectFirst(".positioning h5").text().toIntOrNull() |                     val epNum = it.selectFirst(".positioning h5").text().toIntOrNull() | ||||||
|                     AnimeSearchResponse( |                     newAnimeSearchResponse(title, url) { | ||||||
|                         title, |                         this.posterUrl = fixUrl(poster) | ||||||
|                         url, |                         addDubStatus(getDubStatus(title), epNum) | ||||||
|                         this.name, |                     } | ||||||
|                         TvType.Anime, |  | ||||||
|                         poster, |  | ||||||
|                         null, |  | ||||||
|                         if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of( |  | ||||||
|                             DubStatus.Dubbed |  | ||||||
|                         ) else EnumSet.of(DubStatus.Subbed), |  | ||||||
|                         subEpisodes = epNum, |  | ||||||
|                         dubEpisodes = epNum, |  | ||||||
|                     ) |  | ||||||
|                 }) |                 }) | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|  | @ -71,17 +68,10 @@ class MonoschinosProvider : MainAPI() { | ||||||
|                 val home = app.get(i.first, timeout = 120).document.select(".col-6").map { |                 val home = app.get(i.first, timeout = 120).document.select(".col-6").map { | ||||||
|                     val title = it.selectFirst(".seristitles").text() |                     val title = it.selectFirst(".seristitles").text() | ||||||
|                     val poster = it.selectFirst("img.animemainimg").attr("src") |                     val poster = it.selectFirst("img.animemainimg").attr("src") | ||||||
|                     AnimeSearchResponse( |                     newAnimeSearchResponse(title, fixUrl(it.selectFirst("a").attr("href"))) { | ||||||
|                         title, |                         this.posterUrl = fixUrl(poster) | ||||||
|                         fixUrl(it.selectFirst("a").attr("href")), |                         addDubStatus(getDubStatus(title)) | ||||||
|                         this.name, |                     } | ||||||
|                         TvType.Anime, |  | ||||||
|                         fixUrl(poster), |  | ||||||
|                         null, |  | ||||||
|                         if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of( |  | ||||||
|                             DubStatus.Dubbed |  | ||||||
|                         ) else EnumSet.of(DubStatus.Subbed), |  | ||||||
|                     ) |  | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 items.add(HomePageList(i.second, home)) |                 items.add(HomePageList(i.second, home)) | ||||||
|  |  | ||||||
|  | @ -17,12 +17,25 @@ class NineAnimeProvider : MainAPI() { | ||||||
|     override val hasDownloadSupport = true |     override val hasDownloadSupport = true | ||||||
|     override val supportedTypes = setOf(TvType.Anime) |     override val supportedTypes = setOf(TvType.Anime) | ||||||
| 
 | 
 | ||||||
|  |     companion object { | ||||||
|  |         fun getDubStatus(title: String): DubStatus { | ||||||
|  |             return if (title.contains("(dub)", ignoreCase = true)) { | ||||||
|  |                 DubStatus.Dubbed | ||||||
|  |             } else { | ||||||
|  |                 DubStatus.Subbed | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     override suspend fun getMainPage(): HomePageResponse { |     override suspend fun getMainPage(): HomePageResponse { | ||||||
|         val items = listOf( |         val items = listOf( | ||||||
|             Pair("$mainUrl/ajax/home/widget?name=trending", "Trending"), |             Pair("$mainUrl/ajax/home/widget?name=trending", "Trending"), | ||||||
|             Pair("$mainUrl/ajax/home/widget?name=updated_all", "All"), |             Pair("$mainUrl/ajax/home/widget?name=updated_all", "All"), | ||||||
|             Pair("$mainUrl/ajax/home/widget?name=updated_sub&page=1", "Recently Updated (SUB)"), |             Pair("$mainUrl/ajax/home/widget?name=updated_sub&page=1", "Recently Updated (SUB)"), | ||||||
|             Pair("$mainUrl/ajax/home/widget?name=updated_dub&page=1", "Recently Updated (DUB)"), |             Pair( | ||||||
|  |                 "$mainUrl/ajax/home/widget?name=updated_dub&page=1", | ||||||
|  |                 "Recently Updated (DUB)(DUB)" | ||||||
|  |             ), | ||||||
|             Pair( |             Pair( | ||||||
|                 "$mainUrl/ajax/home/widget?name=updated_chinese&page=1", |                 "$mainUrl/ajax/home/widget?name=updated_chinese&page=1", | ||||||
|                 "Recently Updated (Chinese)" |                 "Recently Updated (Chinese)" | ||||||
|  | @ -37,17 +50,11 @@ class NineAnimeProvider : MainAPI() { | ||||||
|                 val title = it.selectFirst("a.name").text() |                 val title = it.selectFirst("a.name").text() | ||||||
|                 val link = it.selectFirst("a").attr("href") |                 val link = it.selectFirst("a").attr("href") | ||||||
|                 val poster = it.selectFirst("a.poster img").attr("src") |                 val poster = it.selectFirst("a.poster img").attr("src") | ||||||
|                 AnimeSearchResponse( | 
 | ||||||
|                     title, |                 newAnimeSearchResponse(title, link) { | ||||||
|                     link, |                     this.posterUrl = poster | ||||||
|                     this.name, |                     addDubStatus(getDubStatus(title)) | ||||||
|                     TvType.Anime, |                 } | ||||||
|                     poster, |  | ||||||
|                     null, |  | ||||||
|                     if (title.contains("(DUB)") || title.contains("(Dub)")) EnumSet.of( |  | ||||||
|                         DubStatus.Dubbed |  | ||||||
|                     ) else EnumSet.of(DubStatus.Subbed), |  | ||||||
|                 ) |  | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             HomePageList(name, home) |             HomePageList(name, home) | ||||||
|  | @ -206,24 +213,18 @@ class NineAnimeProvider : MainAPI() { | ||||||
|             Episode(link, name) |             Episode(link, name) | ||||||
|         } ?: return null |         } ?: return null | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|         val recommendations = |         val recommendations = | ||||||
|             doc.select("div.container aside.main section div.body ul.anime-list li")?.mapNotNull { element -> |             doc.select("div.container aside.main section div.body ul.anime-list li") | ||||||
|                 val recTitle = element.select("a.name").text() ?: return@mapNotNull null |                 ?.mapNotNull { element -> | ||||||
|  |                     val recTitle = element.select("a.name")?.text() ?: return@mapNotNull null | ||||||
|                     val image = element.select("a.poster img")?.attr("src") |                     val image = element.select("a.poster img")?.attr("src") | ||||||
|                     val recUrl = fixUrl(element.select("a").attr("href")) |                     val recUrl = fixUrl(element.select("a").attr("href")) | ||||||
|                 AnimeSearchResponse( |                     newAnimeSearchResponse(recTitle, recUrl) { | ||||||
|                     recTitle, |                         this.posterUrl = image | ||||||
|                     fixUrl(recUrl), |                         addDubStatus(getDubStatus(recTitle)) | ||||||
|                     this.name, |  | ||||||
|                     TvType.Anime, |  | ||||||
|                     image, |  | ||||||
|                     dubStatus = |  | ||||||
|                     if (recTitle.contains("(DUB)") || recTitle.contains("(Dub)")) EnumSet.of( |  | ||||||
|                         DubStatus.Dubbed |  | ||||||
|                     ) else EnumSet.of(DubStatus.Subbed), |  | ||||||
|                 ) |  | ||||||
|                     } |                     } | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|         val infodoc = doc.selectFirst("div.info .meta .col1").text() |         val infodoc = doc.selectFirst("div.info .meta .col1").text() | ||||||
|         val tvType = if (infodoc.contains("Movie")) TvType.AnimeMovie else TvType.Anime |         val tvType = if (infodoc.contains("Movie")) TvType.AnimeMovie else TvType.Anime | ||||||
|         val status = |         val status = | ||||||
|  | @ -231,13 +232,14 @@ class NineAnimeProvider : MainAPI() { | ||||||
|             else if (infodoc.contains("Airing")) ShowStatus.Ongoing |             else if (infodoc.contains("Airing")) ShowStatus.Ongoing | ||||||
|             else null |             else null | ||||||
|         val tags = doc.select("div.info .meta .col1 div:contains(Genre) a").map { it.text() } |         val tags = doc.select("div.info .meta .col1 div:contains(Genre) a").map { it.text() } | ||||||
|  | 
 | ||||||
|         return newAnimeLoadResponse(title, url, tvType) { |         return newAnimeLoadResponse(title, url, tvType) { | ||||||
|             posterUrl = poster |             this.posterUrl = poster | ||||||
|             addEpisodes(DubStatus.Subbed, episodes) |             this.plot = description | ||||||
|             plot = description |  | ||||||
|             this.recommendations = recommendations |             this.recommendations = recommendations | ||||||
|             showStatus = status |             this.showStatus = status | ||||||
|             this.tags = tags |             this.tags = tags | ||||||
|  |             addEpisodes(DubStatus.Subbed, episodes) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -260,7 +262,8 @@ class NineAnimeProvider : MainAPI() { | ||||||
|         callback: (ExtractorLink) -> Unit |         callback: (ExtractorLink) -> Unit | ||||||
|     ): Boolean { |     ): Boolean { | ||||||
|         val document = app.get(data).document |         val document = app.get(data).document | ||||||
|         val animeid = document.selectFirst("div.player-wrapper.watchpage").attr("data-id") ?: return false |         val animeid = | ||||||
|  |             document.selectFirst("div.player-wrapper.watchpage").attr("data-id") ?: return false | ||||||
|         val animeidencoded = encode(getVrf(animeid) ?: return false) |         val animeidencoded = encode(getVrf(animeid) ?: return false) | ||||||
| 
 | 
 | ||||||
|         Jsoup.parse( |         Jsoup.parse( | ||||||
|  | @ -287,7 +290,7 @@ class NineAnimeProvider : MainAPI() { | ||||||
|                         parseJson<Links>(epserver) |                         parseJson<Links>(epserver) | ||||||
|                     } else null)?.url?.let { it1 -> getLink(it1.replace("=", "")) } |                     } else null)?.url?.let { it1 -> getLink(it1.replace("=", "")) } | ||||||
|                         ?.replace("/embed/", "/e/") |                         ?.replace("/embed/", "/e/") | ||||||
|                 } catch (e : Exception) { |                 } catch (e: Exception) { | ||||||
|                     logError(e) |                     logError(e) | ||||||
|                     null |                     null | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  | @ -17,7 +17,6 @@ import okhttp3.Interceptor | ||||||
| import org.jsoup.Jsoup | import org.jsoup.Jsoup | ||||||
| import org.jsoup.nodes.Element | import org.jsoup.nodes.Element | ||||||
| import java.net.URI | import java.net.URI | ||||||
| import java.util.* |  | ||||||
| 
 | 
 | ||||||
| private const val OPTIONS = "OPTIONS" | private const val OPTIONS = "OPTIONS" | ||||||
| 
 | 
 | ||||||
|  | @ -52,29 +51,30 @@ class ZoroProvider : MainAPI() { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     val epRegex = Regex("Ep (\\d+)/") | ||||||
|     private fun Element.toSearchResult(): SearchResponse? { |     private fun Element.toSearchResult(): SearchResponse? { | ||||||
|         val href = fixUrl(this.select("a").attr("href")) |         val href = fixUrl(this.select("a").attr("href")) | ||||||
|         val title = this.select("h3.film-name").text() |         val title = this.select("h3.film-name").text() | ||||||
|         /*val episodes = this.select("div.fd-infor > span.fdi-item")?.get(1)?.text()?.let { eps -> |             val dubSub = this.select(".film-poster > .tick.ltr").text() | ||||||
|  |         //val episodes = this.selectFirst(".film-poster > .tick-eps")?.text()?.toIntOrNull() | ||||||
|  | 
 | ||||||
|  |         val dubExist = dubSub.contains("dub", ignoreCase = true) | ||||||
|  |         val subExist = dubSub.contains("sub", ignoreCase = true) | ||||||
|  |         val episodes = this.selectFirst(".film-poster > .tick.rtl > .tick-eps")?.text()?.let { eps -> | ||||||
|  |             //println("REGEX:::: $eps") | ||||||
|             // current episode / max episode |             // current episode / max episode | ||||||
|             val epRegex = Regex("Ep (\\d+)/")//Regex("Ep (\\d+)/(\\d+)") |             //Regex("Ep (\\d+)/(\\d+)") | ||||||
|             epRegex.find(eps)?.groupValues?.get(1)?.toIntOrNull() |             epRegex.find(eps)?.groupValues?.get(1)?.toIntOrNull() | ||||||
|         }*/ |         } | ||||||
|         if (href.contains("/news/") || title.trim().equals("News", ignoreCase = true)) return null |         if (href.contains("/news/") || title.trim().equals("News", ignoreCase = true)) return null | ||||||
|         val posterUrl = fixUrl(this.select("img").attr("data-src")) |         val posterUrl = fixUrl(this.select("img").attr("data-src")) | ||||||
|         val type = getType(this.select("div.fd-infor > span.fdi-item").text()) |         val type = getType(this.select("div.fd-infor > span.fdi-item").text()) | ||||||
| 
 | 
 | ||||||
|         return AnimeSearchResponse( |         return newAnimeSearchResponse(title, href, type) { | ||||||
|             title, |             this.posterUrl = posterUrl | ||||||
|             href, |             addDubStatus(dubExist, subExist, episodes, episodes) | ||||||
|             this@ZoroProvider.name, |         } | ||||||
|             type, |  | ||||||
|             posterUrl, |  | ||||||
|             null, |  | ||||||
|             null, |  | ||||||
|         ) |  | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
|     override suspend fun getMainPage(): HomePageResponse { |     override suspend fun getMainPage(): HomePageResponse { | ||||||
|         val html = app.get("$mainUrl/home").text |         val html = app.get("$mainUrl/home").text | ||||||
|  | @ -152,30 +152,14 @@ class ZoroProvider : MainAPI() { | ||||||
|             val dubExist = dubsub?.contains("DUB") ?: false |             val dubExist = dubsub?.contains("DUB") ?: false | ||||||
|             val subExist = dubsub?.contains("SUB") ?: false || dubsub?.contains("RAW") ?: false |             val subExist = dubsub?.contains("SUB") ?: false || dubsub?.contains("RAW") ?: false | ||||||
| 
 | 
 | ||||||
|             val set = if (dubExist && subExist) { |  | ||||||
|                 EnumSet.of(DubStatus.Dubbed, DubStatus.Subbed) |  | ||||||
|             } else if (dubExist) { |  | ||||||
|                 EnumSet.of(DubStatus.Dubbed) |  | ||||||
|             } else { |  | ||||||
|                 EnumSet.of(DubStatus.Subbed) |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             val tvType = |             val tvType = | ||||||
|                 getType(it.selectFirst(".film-detail > .fd-infor > .fdi-item")?.text().toString()) |                 getType(it.selectFirst(".film-detail > .fd-infor > .fdi-item")?.text().toString()) | ||||||
|             val href = fixUrl(it.selectFirst(".film-name a").attr("href")) |             val href = fixUrl(it.selectFirst(".film-name a").attr("href")) | ||||||
| 
 | 
 | ||||||
|             AnimeSearchResponse( |             newAnimeSearchResponse(title, href, tvType) { | ||||||
|                 title, |                 this.posterUrl = poster | ||||||
|                 href, |                 addDubStatus(dubExist, subExist, episodes, episodes) | ||||||
|                 name, |             } | ||||||
|                 tvType, |  | ||||||
|                 poster, |  | ||||||
|                 null, |  | ||||||
|                 set, |  | ||||||
|                 null, |  | ||||||
|                 if (dubExist) episodes else null, |  | ||||||
|                 if (subExist) episodes else null, |  | ||||||
|             ) |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -187,8 +171,8 @@ class ZoroProvider : MainAPI() { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     data class ZoroSyncData( |     data class ZoroSyncData( | ||||||
|         @JsonProperty("mal_id") val malId : String?, |         @JsonProperty("mal_id") val malId: String?, | ||||||
|         @JsonProperty("anilist_id") val aniListId : String?, |         @JsonProperty("anilist_id") val aniListId: String?, | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     override suspend fun load(url: String): LoadResponse { |     override suspend fun load(url: String): LoadResponse { | ||||||
|  |  | ||||||
|  | @ -14,6 +14,11 @@ class DoramasYTProvider : MainAPI() { | ||||||
|             else if (t.contains("Pelicula")) TvType.Movie |             else if (t.contains("Pelicula")) TvType.Movie | ||||||
|             else TvType.TvSeries |             else TvType.TvSeries | ||||||
|         } |         } | ||||||
|  |         fun getDubStatus(title: String): DubStatus { | ||||||
|  |             return if (title.contains("Latino") || title.contains("Castellano")) | ||||||
|  |                 DubStatus.Dubbed | ||||||
|  |             else DubStatus.Subbed | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override var mainUrl = "https://doramasyt.com" |     override var mainUrl = "https://doramasyt.com" | ||||||
|  | @ -53,39 +58,22 @@ class DoramasYTProvider : MainAPI() { | ||||||
|                     val url = it.selectFirst("a").attr("href").replace("ver/", "dorama/") |                     val url = it.selectFirst("a").attr("href").replace("ver/", "dorama/") | ||||||
|                         .replace(epRegex, "sub-espanol") |                         .replace(epRegex, "sub-espanol") | ||||||
|                     val epNum = it.selectFirst("h3").text().toIntOrNull() |                     val epNum = it.selectFirst("h3").text().toIntOrNull() | ||||||
|                     AnimeSearchResponse( |                     newAnimeSearchResponse(title,url) { | ||||||
|                         title, |                         this.posterUrl = fixUrl(poster) | ||||||
|                         url, |                         addDubStatus(getDubStatus(title), epNum) | ||||||
|                         this.name, |                     } | ||||||
|                         TvType.Anime, |  | ||||||
|                         poster, |  | ||||||
|                         null, |  | ||||||
|                         if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of( |  | ||||||
|                             DubStatus.Dubbed |  | ||||||
|                         ) else EnumSet.of(DubStatus.Subbed), |  | ||||||
|                         subEpisodes = epNum, |  | ||||||
|                         dubEpisodes = epNum, |  | ||||||
|                     ) |  | ||||||
|                 }) |                 }) | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|         for (i in urls) { |         for (i in urls) { | ||||||
|             try { |             try { | ||||||
| 
 |  | ||||||
|                 val home = app.get(i.first, timeout = 120).document.select(".col-6").map { |                 val home = app.get(i.first, timeout = 120).document.select(".col-6").map { | ||||||
|                     val title = it.selectFirst(".animedtls p").text() |                     val title = it.selectFirst(".animedtls p").text() | ||||||
|                     val poster = it.selectFirst(".anithumb img").attr("src") |                     val poster = it.selectFirst(".anithumb img").attr("src") | ||||||
|                     AnimeSearchResponse( |                     newAnimeSearchResponse(title, fixUrl(it.selectFirst("a").attr("href"))) { | ||||||
|                         title, |                         this.posterUrl = fixUrl(poster) | ||||||
|                         it.selectFirst("a").attr("href"), |                         addDubStatus(getDubStatus(title)) | ||||||
|                         this.name, |                     } | ||||||
|                         TvType.Anime, |  | ||||||
|                         poster, |  | ||||||
|                         null, |  | ||||||
|                         if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of( |  | ||||||
|                             DubStatus.Dubbed |  | ||||||
|                         ) else EnumSet.of(DubStatus.Subbed), |  | ||||||
|                     ) |  | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 items.add(HomePageList(i.second, home)) |                 items.add(HomePageList(i.second, home)) | ||||||
|  |  | ||||||
|  | @ -85,7 +85,7 @@ open class VidstreamProviderTemplate : MainAPI() { | ||||||
| 
 | 
 | ||||||
|         val description = soup.selectFirst(".post-entry")?.text()?.trim() |         val description = soup.selectFirst(".post-entry")?.text()?.trim() | ||||||
|         var poster: String? = null |         var poster: String? = null | ||||||
|         var year : Int? = null |         var year: Int? = null | ||||||
| 
 | 
 | ||||||
|         val episodes = |         val episodes = | ||||||
|             soup.select(".listing.items.lists > .video-block").withIndex().map { (_, li) -> |             soup.select(".listing.items.lists > .video-block").withIndex().map { (_, li) -> | ||||||
|  | @ -105,7 +105,7 @@ open class VidstreamProviderTemplate : MainAPI() { | ||||||
| 
 | 
 | ||||||
|                 val epNum = Regex("""Episode (\d+)""").find(epTitle)?.destructured?.component1() |                 val epNum = Regex("""Episode (\d+)""").find(epTitle)?.destructured?.component1() | ||||||
|                     ?.toIntOrNull() |                     ?.toIntOrNull() | ||||||
|                 if(year == null) { |                 if (year == null) { | ||||||
|                     year = epDate?.split("-")?.get(0)?.toIntOrNull() |                     year = epDate?.split("-")?.get(0)?.toIntOrNull() | ||||||
|                 } |                 } | ||||||
|                 newEpisode(li.selectFirst("a").attr("href")) { |                 newEpisode(li.selectFirst("a").attr("href")) { | ||||||
|  | @ -173,25 +173,13 @@ open class VidstreamProviderTemplate : MainAPI() { | ||||||
|                     val isSeries = (name.contains("Season") || name.contains("Episode")) |                     val isSeries = (name.contains("Season") || name.contains("Episode")) | ||||||
| 
 | 
 | ||||||
|                     if (isSeries) { |                     if (isSeries) { | ||||||
|                         TvSeriesSearchResponse( |                         newTvSeriesSearchResponse(name, link) { | ||||||
|                             name, |                             posterUrl = image | ||||||
|                             link, |                         } | ||||||
|                             this.name, |  | ||||||
|                             TvType.TvSeries, |  | ||||||
|                             image, |  | ||||||
|                             null, |  | ||||||
|                             null, |  | ||||||
|                         ) |  | ||||||
|                     } else { |                     } else { | ||||||
|                         MovieSearchResponse( |                         newMovieSearchResponse(name, link) { | ||||||
|                             name, |                             posterUrl = image | ||||||
|                             link, |                         } | ||||||
|                             this.name, |  | ||||||
|                             TvType.Movie, |  | ||||||
|                             image, |  | ||||||
|                             null, |  | ||||||
|                             null, |  | ||||||
|                         ) |  | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -770,7 +770,7 @@ class HomeFragment : Fragment() { | ||||||
| 
 | 
 | ||||||
|                     home_main_text?.text = |                     home_main_text?.text = | ||||||
|                         random.name + if (random is AnimeSearchResponse && !random.dubStatus.isNullOrEmpty()) { |                         random.name + if (random is AnimeSearchResponse && !random.dubStatus.isNullOrEmpty()) { | ||||||
|                             random.dubStatus.joinToString( |                             random.dubStatus?.joinToString( | ||||||
|                                 prefix = " • ", |                                 prefix = " • ", | ||||||
|                                 separator = " | " |                                 separator = " | " | ||||||
|                             ) { it.name } |                             ) { it.name } | ||||||
|  |  | ||||||
|  | @ -710,7 +710,8 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio | ||||||
|                         CastButtonFactory.setUpMediaRouteButton(act, media_route_button) |                         CastButtonFactory.setUpMediaRouteButton(act, media_route_button) | ||||||
|                         val castContext = CastContext.getSharedInstance(act.applicationContext) |                         val castContext = CastContext.getSharedInstance(act.applicationContext) | ||||||
| 
 | 
 | ||||||
|                         media_route_button?.isGone = castContext.castState == CastState.NO_DEVICES_AVAILABLE |                         media_route_button?.isGone = | ||||||
|  |                             castContext.castState == CastState.NO_DEVICES_AVAILABLE | ||||||
| 
 | 
 | ||||||
|                         castContext.addCastStateListener { state -> |                         castContext.addCastStateListener { state -> | ||||||
|                             media_route_button?.isGone = state == CastState.NO_DEVICES_AVAILABLE |                             media_route_button?.isGone = state == CastState.NO_DEVICES_AVAILABLE | ||||||
|  | @ -1299,7 +1300,6 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         observe(syncModel.syncIds) { |         observe(syncModel.syncIds) { | ||||||
|             println("VALUES::: $it") |  | ||||||
|             syncdata = it |             syncdata = it | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -1657,8 +1657,8 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio | ||||||
| 
 | 
 | ||||||
|                     val posterImageLink = d.posterUrl |                     val posterImageLink = d.posterUrl | ||||||
|                     if (!posterImageLink.isNullOrEmpty()) { |                     if (!posterImageLink.isNullOrEmpty()) { | ||||||
|                         result_poster?.setImage(posterImageLink) |                         result_poster?.setImage(posterImageLink, d.posterHeaders) | ||||||
|                         result_poster_blur?.setImageBlur(posterImageLink, 10, 3) |                         result_poster_blur?.setImageBlur(posterImageLink, 10, 3, d.posterHeaders) | ||||||
|                         //Full screen view of Poster image |                         //Full screen view of Poster image | ||||||
|                         if (context?.isTrueTvSettings() == false) // Poster not clickable on tv |                         if (context?.isTrueTvSettings() == false) // Poster not clickable on tv | ||||||
|                             result_poster_holder?.setOnClickListener { |                             result_poster_holder?.setOnClickListener { | ||||||
|  |  | ||||||
|  | @ -52,7 +52,8 @@ class SearchFragment : Fragment() { | ||||||
|         fun List<SearchResponse>.filterSearchResponse(): List<SearchResponse> { |         fun List<SearchResponse>.filterSearchResponse(): List<SearchResponse> { | ||||||
|             return this.filter { response -> |             return this.filter { response -> | ||||||
|                 if (response is AnimeSearchResponse) { |                 if (response is AnimeSearchResponse) { | ||||||
|                     (response.dubStatus.isNullOrEmpty()) || (response.dubStatus.any { |                     val status = response.dubStatus | ||||||
|  |                     (status.isNullOrEmpty()) || (status.any { | ||||||
|                         APIRepository.dubStatusActive.contains(it) |                         APIRepository.dubStatusActive.contains(it) | ||||||
|                     }) |                     }) | ||||||
|                 } else { |                 } else { | ||||||
|  | @ -225,11 +226,13 @@ class SearchFragment : Fragment() { | ||||||
|                             } |                             } | ||||||
|                         }.sortedBy { it.name.lowercase() } |                         }.sortedBy { it.name.lowercase() } | ||||||
| 
 | 
 | ||||||
|                         val names = currentValidApis.map {  if(isMultiLang) "${ |                         val names = currentValidApis.map { | ||||||
|  |                             if (isMultiLang) "${ | ||||||
|                                 SubtitleHelper.getFlagFromIso( |                                 SubtitleHelper.getFlagFromIso( | ||||||
|                                     it.lang |                                     it.lang | ||||||
|                                 )?.plus(" ") ?: "" |                                 )?.plus(" ") ?: "" | ||||||
|                         }${it.name}" else it.name } |                             }${it.name}" else it.name | ||||||
|  |                         } | ||||||
|                         for ((index, api) in currentValidApis.map { it.name }.withIndex()) { |                         for ((index, api) in currentValidApis.map { it.name }.withIndex()) { | ||||||
|                             listView?.setItemChecked(index, currentSelectedApis.contains(api)) |                             listView?.setItemChecked(index, currentSelectedApis.contains(api)) | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|  | @ -47,7 +47,7 @@ object SearchResultBuilder { | ||||||
|         textIsDub?.isVisible = false |         textIsDub?.isVisible = false | ||||||
|         textIsSub?.isVisible = false |         textIsSub?.isVisible = false | ||||||
| 
 | 
 | ||||||
|         when(card.quality) { |         when (card.quality) { | ||||||
|             SearchQuality.BlueRay -> R.string.quality_blueray |             SearchQuality.BlueRay -> R.string.quality_blueray | ||||||
|             SearchQuality.Cam -> R.string.quality_cam |             SearchQuality.Cam -> R.string.quality_cam | ||||||
|             SearchQuality.CamRip -> R.string.quality_cam_rip |             SearchQuality.CamRip -> R.string.quality_cam_rip | ||||||
|  | @ -75,7 +75,7 @@ object SearchResultBuilder { | ||||||
|         cardText?.text = card.name |         cardText?.text = card.name | ||||||
| 
 | 
 | ||||||
|         cardView.isVisible = true |         cardView.isVisible = true | ||||||
|         if (!cardView.setImage(card.posterUrl)) { |         if (!cardView.setImage(card.posterUrl, card.posterHeaders)) { | ||||||
|             cardView.setImageResource(R.drawable.default_cover) |             cardView.setImageResource(R.drawable.default_cover) | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -182,20 +182,24 @@ object SearchResultBuilder { | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             is AnimeSearchResponse -> { |             is AnimeSearchResponse -> { | ||||||
|                 if (card.dubStatus != null && card.dubStatus.size > 0) { |                 val dubStatus = card.dubStatus | ||||||
|                     if (card.dubStatus.contains(DubStatus.Dubbed)) { |                 if (!dubStatus.isNullOrEmpty()) { | ||||||
|  |                     if (dubStatus.contains(DubStatus.Dubbed)) { | ||||||
|                         textIsDub?.visibility = View.VISIBLE |                         textIsDub?.visibility = View.VISIBLE | ||||||
|                     } |                     } | ||||||
|                     if (card.dubStatus.contains(DubStatus.Subbed)) { |                     if (dubStatus.contains(DubStatus.Subbed)) { | ||||||
|                         textIsSub?.visibility = View.VISIBLE |                         textIsSub?.visibility = View.VISIBLE | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|  |                 val dubEpisodes = card.episodes[DubStatus.Dubbed] | ||||||
|  |                 val subEpisodes = card.episodes[DubStatus.Subbed] | ||||||
|  | 
 | ||||||
|                 textIsDub?.apply { |                 textIsDub?.apply { | ||||||
|                     val dubText = context.getString(R.string.app_dubbed_text) |                     val dubText = context.getString(R.string.app_dubbed_text) | ||||||
|                     text = if (card.dubEpisodes != null && card.dubEpisodes > 0) { |                     text = if (dubEpisodes != null && dubEpisodes > 0) { | ||||||
|                         context.getString(R.string.app_dub_sub_episode_text_format) |                         context.getString(R.string.app_dub_sub_episode_text_format) | ||||||
|                             .format(dubText, card.dubEpisodes) |                             .format(dubText, dubEpisodes) | ||||||
|                     } else { |                     } else { | ||||||
|                         dubText |                         dubText | ||||||
|                     } |                     } | ||||||
|  | @ -203,9 +207,9 @@ object SearchResultBuilder { | ||||||
| 
 | 
 | ||||||
|                 textIsSub?.apply { |                 textIsSub?.apply { | ||||||
|                     val subText = context.getString(R.string.app_subbed_text) |                     val subText = context.getString(R.string.app_subbed_text) | ||||||
|                     text = if (card.subEpisodes != null && card.subEpisodes > 0) { |                     text = if (subEpisodes != null && subEpisodes > 0) { | ||||||
|                         context.getString(R.string.app_dub_sub_episode_text_format) |                         context.getString(R.string.app_dub_sub_episode_text_format) | ||||||
|                             .format(subText, card.subEpisodes) |                             .format(subText, subEpisodes) | ||||||
|                     } else { |                     } else { | ||||||
|                         subText |                         subText | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|  | @ -16,7 +16,8 @@ class SyncSearchViewModel { | ||||||
|         override var type: TvType?, |         override var type: TvType?, | ||||||
|         override var posterUrl: String?, |         override var posterUrl: String?, | ||||||
|         override var id: Int?, |         override var id: Int?, | ||||||
|         override var quality: SearchQuality? = null |         override var quality: SearchQuality? = null, | ||||||
|  |         override var posterHeaders: Map<String, String>? = null, | ||||||
|     ) : SearchResponse |     ) : SearchResponse | ||||||
| 
 | 
 | ||||||
|     private fun SyncAPI.SyncSearchResult.toSearchResponse(): SyncSearchResultSearchResponse { |     private fun SyncAPI.SyncSearchResult.toSearchResponse(): SyncSearchResultSearchResponse { | ||||||
|  |  | ||||||
|  | @ -43,7 +43,8 @@ object DataStoreHelper { | ||||||
|         @JsonProperty("type") override var type: TvType? = null, |         @JsonProperty("type") override var type: TvType? = null, | ||||||
|         @JsonProperty("posterUrl") override var posterUrl: String?, |         @JsonProperty("posterUrl") override var posterUrl: String?, | ||||||
|         @JsonProperty("year") val year: Int?, |         @JsonProperty("year") val year: Int?, | ||||||
|         @JsonProperty("quality") override var quality: SearchQuality? = null |         @JsonProperty("quality") override var quality: SearchQuality? = null, | ||||||
|  |         @JsonProperty("posterHeaders") override var posterHeaders: Map<String, String>? = null, | ||||||
|     ) : SearchResponse |     ) : SearchResponse | ||||||
| 
 | 
 | ||||||
|     data class ResumeWatchingResult( |     data class ResumeWatchingResult( | ||||||
|  | @ -60,7 +61,8 @@ object DataStoreHelper { | ||||||
|         @JsonProperty("episode") val episode: Int?, |         @JsonProperty("episode") val episode: Int?, | ||||||
|         @JsonProperty("season") val season: Int?, |         @JsonProperty("season") val season: Int?, | ||||||
|         @JsonProperty("isFromDownload") val isFromDownload: Boolean, |         @JsonProperty("isFromDownload") val isFromDownload: Boolean, | ||||||
|         @JsonProperty("quality") override var quality: SearchQuality? = null |         @JsonProperty("quality") override var quality: SearchQuality? = null, | ||||||
|  |         @JsonProperty("posterHeaders") override var posterHeaders: Map<String, String>? = null, | ||||||
|     ) : SearchResponse |     ) : SearchResponse | ||||||
| 
 | 
 | ||||||
|     var currentAccount: String = "0" //TODO ACCOUNT IMPLEMENTATION |     var currentAccount: String = "0" //TODO ACCOUNT IMPLEMENTATION | ||||||
|  |  | ||||||
|  | @ -148,11 +148,11 @@ object UIHelper { | ||||||
|         return color |         return color | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun ImageView?.setImage(url: String?): Boolean { |     fun ImageView?.setImage(url: String?, headers: Map<String, String>? = null): Boolean { | ||||||
|         if (this == null || url.isNullOrBlank()) return false |         if (this == null || url.isNullOrBlank()) return false | ||||||
|         return try { |         return try { | ||||||
|             GlideApp.with(this.context) |             GlideApp.with(this.context) | ||||||
|                 .load(GlideUrl(url)).transition( |                 .load(GlideUrl(url) { headers ?: emptyMap() }).transition( | ||||||
|                     DrawableTransitionOptions.withCrossFade() |                     DrawableTransitionOptions.withCrossFade() | ||||||
|                 ) |                 ) | ||||||
|                 .into(this) |                 .into(this) | ||||||
|  | @ -163,11 +163,17 @@ object UIHelper { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun ImageView?.setImageBlur(url: String?, radius: Int, sample: Int = 3) { |     fun ImageView?.setImageBlur( | ||||||
|  |         url: String?, | ||||||
|  |         radius: Int, | ||||||
|  |         sample: Int = 3, | ||||||
|  |         headers: Map<String, String>? = null | ||||||
|  |     ) { | ||||||
|         if (this == null || url.isNullOrBlank()) return |         if (this == null || url.isNullOrBlank()) return | ||||||
|         try { |         try { | ||||||
|             GlideApp.with(this.context) |             GlideApp.with(this.context) | ||||||
|                 .load(GlideUrl(url)).apply(bitmapTransform(BlurTransformation(radius, sample))) |                 .load(GlideUrl(url) { headers ?: emptyMap() }) | ||||||
|  |                 .apply(bitmapTransform(BlurTransformation(radius, sample))) | ||||||
|                 .transition( |                 .transition( | ||||||
|                     DrawableTransitionOptions.withCrossFade() |                     DrawableTransitionOptions.withCrossFade() | ||||||
|                 ) |                 ) | ||||||
|  |  | ||||||
|  | @ -24,6 +24,11 @@ | ||||||
|             android:layout_height="match_parent" |             android:layout_height="match_parent" | ||||||
|             android:foreground="?android:attr/selectableItemBackgroundBorderless" |             android:foreground="?android:attr/selectableItemBackgroundBorderless" | ||||||
|             android:contentDescription="@string/search_poster_img_des" /> |             android:contentDescription="@string/search_poster_img_des" /> | ||||||
|  |     <TextView | ||||||
|  |             tools:text="@string/quality_hd" | ||||||
|  |             android:id="@+id/text_quality" | ||||||
|  |             style="@style/SearchBox" | ||||||
|  |             android:background="@drawable/type_bg_color"/> | ||||||
|     <!-- |     <!-- | ||||||
|     <LinearLayout |     <LinearLayout | ||||||
|             android:orientation="vertical" |             android:orientation="vertical" | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue