mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	removed slug
This commit is contained in:
		
							parent
							
								
									9695c980d6
								
							
						
					
					
						commit
						891d9b717f
					
				
					 23 changed files with 223 additions and 158 deletions
				
			
		|  | @ -98,7 +98,7 @@ abstract class MainAPI { | |||
|         return null | ||||
|     } | ||||
| 
 | ||||
|     open fun load(slug: String): LoadResponse? { | ||||
|     open fun load(url: String): LoadResponse? { | ||||
|         return null | ||||
|     } | ||||
| 
 | ||||
|  | @ -185,7 +185,6 @@ class HomePageList( | |||
| interface SearchResponse { | ||||
|     val name: String | ||||
|     val url: String // PUBLIC URL FOR OPEN IN APP | ||||
|     val slug: String // USED FOR INTERNAL DATA | ||||
|     val apiName: String | ||||
|     val type: TvType | ||||
|     val posterUrl: String? | ||||
|  | @ -195,7 +194,6 @@ interface SearchResponse { | |||
| data class AnimeSearchResponse( | ||||
|     override val name: String, | ||||
|     override val url: String, | ||||
|     override val slug: String, | ||||
|     override val apiName: String, | ||||
|     override val type: TvType, | ||||
| 
 | ||||
|  | @ -211,7 +209,6 @@ data class AnimeSearchResponse( | |||
| data class MovieSearchResponse( | ||||
|     override val name: String, | ||||
|     override val url: String, | ||||
|     override val slug: String, | ||||
|     override val apiName: String, | ||||
|     override val type: TvType, | ||||
| 
 | ||||
|  | @ -222,7 +219,6 @@ data class MovieSearchResponse( | |||
| data class TvSeriesSearchResponse( | ||||
|     override val name: String, | ||||
|     override val url: String, | ||||
|     override val slug: String, | ||||
|     override val apiName: String, | ||||
|     override val type: TvType, | ||||
| 
 | ||||
|  |  | |||
|  | @ -160,7 +160,7 @@ class MainActivity : AppCompatActivity() { | |||
|             } else { | ||||
|                 for (api in apis) { | ||||
|                     if (str.startsWith(api.mainUrl)) { | ||||
|                         loadResult(str, str, api.name) | ||||
|                         loadResult(str, api.name) | ||||
|                         break | ||||
|                     } | ||||
|                 } | ||||
|  |  | |||
|  | @ -84,13 +84,12 @@ class DubbedAnimeProvider : MainAPI() { | |||
|             returnValue.add( | ||||
|                 if (getIsMovie(href)) { | ||||
|                     MovieSearchResponse( | ||||
|                         title, href, getSlug(href), this.name, TvType.Movie, img, null | ||||
|                         title, href, this.name, TvType.Movie, img, null | ||||
|                     ) | ||||
|                 } else { | ||||
|                     AnimeSearchResponse( | ||||
|                         title, | ||||
|                         href, | ||||
|                         getSlug(href), | ||||
|                         this.name, | ||||
|                         TvType.Anime, | ||||
|                         img, | ||||
|  | @ -122,13 +121,12 @@ class DubbedAnimeProvider : MainAPI() { | |||
|             returnValue.add( | ||||
|                 if (getIsMovie(href)) { | ||||
|                     MovieSearchResponse( | ||||
|                         title, href, getSlug(href), this.name, TvType.Movie, img, null | ||||
|                         title, href, this.name, TvType.Movie, img, null | ||||
|                     ) | ||||
|                 } else { | ||||
|                     AnimeSearchResponse( | ||||
|                         title, | ||||
|                         href, | ||||
|                         getSlug(href), | ||||
|                         this.name, | ||||
|                         TvType.Anime, | ||||
|                         img, | ||||
|  | @ -183,7 +181,8 @@ class DubbedAnimeProvider : MainAPI() { | |||
|         return true | ||||
|     } | ||||
| 
 | ||||
|     override fun load(slug: String): LoadResponse { | ||||
|     override fun load(url: String): LoadResponse { | ||||
|         val slug = url.replace("$mainUrl/","") | ||||
|         if (getIsMovie(slug)) { | ||||
|             val realSlug = slug.replace("movies/", "") | ||||
|             val episode = getAnimeEpisode(realSlug, true) | ||||
|  |  | |||
|  | @ -165,7 +165,6 @@ class ShiroProvider : MainAPI() { | |||
|             return@map AnimeSearchResponse( | ||||
|                 data.name.replace("Dubbed", ""), // i.english ?: i.canonicalTitle, | ||||
|                 "$mainUrl/anime/${data.slug}", | ||||
|                 data.slug, | ||||
|                 this.name, | ||||
|                 type, | ||||
|                 "https://cdn.shiro.is/${data.image}", | ||||
|  | @ -193,7 +192,6 @@ class ShiroProvider : MainAPI() { | |||
|         return AnimeSearchResponse( | ||||
|             data.name.replace("Dubbed", ""), // i.english ?: i.canonicalTitle, | ||||
|             "$mainUrl/anime/${data.slug}", | ||||
|             data.slug, | ||||
|             this.name, | ||||
|             type, | ||||
|             "https://cdn.shiro.is/${data.image}", | ||||
|  | @ -264,8 +262,9 @@ class ShiroProvider : MainAPI() { | |||
|         return returnValue | ||||
|     } | ||||
| 
 | ||||
|     override fun load(slug: String): LoadResponse? { | ||||
|     override fun load(url: String): LoadResponse? { | ||||
|         if (!autoLoadToken()) return null | ||||
|         val slug = url.replace("$mainUrl/anime/", "").replace("$mainUrl/", "") | ||||
|         val rurl = "https://tapi.shiro.is/anime/slug/${slug}?token=${token}" | ||||
|         val response = khttp.get(rurl, timeout = 120.0) | ||||
|         val mapped = response.let { mapper.readValue<AnimePage>(it.text) } | ||||
|  | @ -286,7 +285,7 @@ class ShiroProvider : MainAPI() { | |||
|             data.english, | ||||
|             data.japanese, | ||||
|             data.name.replace("Dubbed", ""),//data.canonicalTitle ?: data.name.replace("Dubbed", ""), | ||||
|             "$mainUrl/anime/${slug}", | ||||
|             "$mainUrl/anime/${url}", | ||||
|             this.name, | ||||
|             getType(data.type ?: ""), | ||||
|             "https://cdn.shiro.is/${data.image}", | ||||
|  |  | |||
|  | @ -54,10 +54,6 @@ class TenshiProvider : MainAPI() { | |||
|         return movies.contains(aniId) | ||||
|     } | ||||
| 
 | ||||
|     private fun getSlug(href: String): String { | ||||
|         return href.replace("$mainUrl/anime/", "") | ||||
|     } | ||||
| 
 | ||||
|     private fun parseSearchPage(soup: Document): ArrayList<SearchResponse> { | ||||
|         val items = soup.select("ul.thumb > li > a") | ||||
|         if (items.isEmpty()) return ArrayList() | ||||
|  | @ -70,13 +66,12 @@ class TenshiProvider : MainAPI() { | |||
|             returnValue.add( | ||||
|                 if (getIsMovie(href, true)) { | ||||
|                     MovieSearchResponse( | ||||
|                         title, href, getSlug(href), this.name, TvType.Movie, img, null | ||||
|                         title, href, this.name, TvType.Movie, img, null | ||||
|                     ) | ||||
|                 } else { | ||||
|                     AnimeSearchResponse( | ||||
|                         title, | ||||
|                         href, | ||||
|                         getSlug(href), | ||||
|                         this.name, | ||||
|                         TvType.Anime, | ||||
|                         img, | ||||
|  | @ -170,9 +165,7 @@ class TenshiProvider : MainAPI() { | |||
|         return returnValue | ||||
|     } | ||||
| 
 | ||||
|     override fun load(slug: String): LoadResponse { | ||||
|         val url = "$mainUrl/anime/${slug}" | ||||
| 
 | ||||
|     override fun load(url: String): LoadResponse { | ||||
|         val response = khttp.get(url, timeout = 120.0, cookies=mapOf("loop-view" to "thumb")) | ||||
|         val document = Jsoup.parse(response.text) | ||||
| 
 | ||||
|  | @ -213,7 +206,7 @@ class TenshiProvider : MainAPI() { | |||
|             englishTitle, | ||||
|             japaneseTitle, | ||||
|             canonicalTitle, | ||||
|             "$mainUrl/anime/${slug}", | ||||
|             url, | ||||
|             this.name, | ||||
|             TenshiProvider.getType(type ?: ""), | ||||
|             poster, | ||||
|  |  | |||
|  | @ -25,11 +25,6 @@ class WcoProvider : MainAPI() { | |||
|     override val hasQuickSearch: Boolean | ||||
|         get() = true | ||||
| 
 | ||||
| 
 | ||||
|     private fun getSlug(href: String): String { | ||||
|         return href.replace("$mainUrl/anime/", "").replace("/", "") | ||||
|     } | ||||
| 
 | ||||
|     private fun fixAnimeLink(url: String): String { | ||||
|         val regex = "watch/([a-zA-Z\\-0-9]*)-episode".toRegex() | ||||
|         val (aniId) = regex.find(url)!!.destructured | ||||
|  | @ -51,13 +46,12 @@ class WcoProvider : MainAPI() { | |||
|             returnValue.add( | ||||
|                 if (getType(type) == TvType.Movie) { | ||||
|                     MovieSearchResponse( | ||||
|                         title, href, getSlug(href), this.name, TvType.Movie, img, year | ||||
|                         title, href, this.name, TvType.Movie, img, year | ||||
|                     ) | ||||
|                 } else { | ||||
|                     AnimeSearchResponse( | ||||
|                         title, | ||||
|                         href, | ||||
|                         getSlug(href), | ||||
|                         this.name, | ||||
|                         TvType.Anime, | ||||
|                         img, | ||||
|  | @ -113,13 +107,12 @@ class WcoProvider : MainAPI() { | |||
|                 returnValue.add( | ||||
|                     if (getType(type) == TvType.Movie) { | ||||
|                         MovieSearchResponse( | ||||
|                             title, href, getSlug(href), this.name, TvType.Movie, img, year | ||||
|                             title, href, this.name, TvType.Movie, img, year | ||||
|                         ) | ||||
|                     } else { | ||||
|                         AnimeSearchResponse( | ||||
|                             title, | ||||
|                             href, | ||||
|                             getSlug(href), | ||||
|                             this.name, | ||||
|                             TvType.Anime, | ||||
|                             img, | ||||
|  | @ -136,9 +129,7 @@ class WcoProvider : MainAPI() { | |||
|         return returnValue | ||||
|     } | ||||
| 
 | ||||
|     override fun load(slug: String): LoadResponse { | ||||
|         val url = "$mainUrl/anime/${slug}" | ||||
| 
 | ||||
|     override fun load(url: String): LoadResponse { | ||||
|         val response = khttp.get(url, timeout = 120.0) | ||||
|         val document = Jsoup.parse(response.text) | ||||
| 
 | ||||
|  | @ -174,7 +165,7 @@ class WcoProvider : MainAPI() { | |||
|             canonicalTitle, | ||||
|             japaneseTitle, | ||||
|             canonicalTitle, | ||||
|             "$mainUrl/anime/${slug}", | ||||
|             url, | ||||
|             this.name, | ||||
|             getType(type ?: ""), | ||||
|             poster, | ||||
|  |  | |||
|  | @ -25,7 +25,7 @@ class HDMProvider : MainAPI() { | |||
|             val data = i.selectFirst("> div.item") | ||||
|             val img = data.selectFirst("> img").attr("src") | ||||
|             val name = data.selectFirst("> div.movie-details").text() | ||||
|             returnValue.add(MovieSearchResponse(name, href, href, this.name, TvType.Movie, img, null)) | ||||
|             returnValue.add(MovieSearchResponse(name, href, this.name, TvType.Movie, img, null)) | ||||
|         } | ||||
| 
 | ||||
|         return returnValue | ||||
|  | @ -54,8 +54,8 @@ class HDMProvider : MainAPI() { | |||
|         return true | ||||
|     } | ||||
| 
 | ||||
|     override fun load(slug: String): LoadResponse? { | ||||
|         val response = khttp.get(slug) | ||||
|     override fun load(url: String): LoadResponse? { | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val title = document.selectFirst("h2.movieTitle").text() | ||||
|         val poster = document.selectFirst("div.post-thumbnail > img").attr("src") | ||||
|  | @ -65,7 +65,7 @@ class HDMProvider : MainAPI() { | |||
|         val data = "src/player/\\?v=(.*?)\"".toRegex().find(response.text)?.groupValues?.get(1) ?: return null | ||||
| 
 | ||||
|         return MovieLoadResponse( | ||||
|             title, slug, this.name, TvType.Movie, | ||||
|             title, url, this.name, TvType.Movie, | ||||
|                 "$mainUrl/src/player/?v=$data", poster, year, descript, null | ||||
|         ) | ||||
|     } | ||||
|  |  | |||
|  | @ -80,7 +80,6 @@ class LookMovieProvider : MainAPI() { | |||
|                     MovieSearchResponse( | ||||
|                         m.title, | ||||
|                         url, | ||||
|                         url,//m.slug, | ||||
|                         this.name, | ||||
|                         TvType.Movie, | ||||
|                         m.poster ?: m.backdrop, | ||||
|  | @ -97,7 +96,6 @@ class LookMovieProvider : MainAPI() { | |||
|                     MovieSearchResponse( | ||||
|                         s.title, | ||||
|                         url, | ||||
|                         url,//s.slug, | ||||
|                         this.name, | ||||
|                         TvType.TvSeries, | ||||
|                         s.poster ?: s.backdrop, | ||||
|  | @ -129,11 +127,11 @@ class LookMovieProvider : MainAPI() { | |||
|                 returnValue.add( | ||||
|                     if (isMovie) { | ||||
|                         MovieSearchResponse( | ||||
|                             name, href, href, this.name, TvType.Movie, poster, year | ||||
|                             name, href, this.name, TvType.Movie, poster, year | ||||
|                         ) | ||||
|                     } else | ||||
|                         TvSeriesSearchResponse( | ||||
|                             name, href, href, this.name, TvType.TvSeries, poster, year, null | ||||
|                             name, href, this.name, TvType.TvSeries, poster, year, null | ||||
|                         ) | ||||
|                 ) | ||||
|             } | ||||
|  | @ -196,10 +194,10 @@ class LookMovieProvider : MainAPI() { | |||
|         return true | ||||
|     } | ||||
| 
 | ||||
|     override fun load(slug: String): LoadResponse? { | ||||
|         val response = khttp.get(slug) | ||||
|     override fun load(url: String): LoadResponse? { | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val isMovie = slug.contains("/movies/") | ||||
|         val isMovie = url.contains("/movies/") | ||||
| 
 | ||||
|         val watchHeader = document.selectFirst("div.watch-heading") | ||||
|         val nameHeader = watchHeader.selectFirst("> h1.bd-hd") | ||||
|  | @ -214,7 +212,7 @@ class LookMovieProvider : MainAPI() { | |||
|         val id = "${if (isMovie) "id_movie" else "id_show"}:(.*?),".toRegex().find(response.text)?.groupValues?.get(1) | ||||
|             ?.replace(" ", "") | ||||
|             ?: return null | ||||
|         val realSlug = slug.replace("$mainUrl/${if (isMovie) "movies" else "shows"}/view/", "") | ||||
|         val realSlug = url.replace("$mainUrl/${if (isMovie) "movies" else "shows"}/view/", "") | ||||
|         val realUrl = | ||||
|             "$mainUrl/api/v1/security/${if (isMovie) "movie" else "show"}-access?${if (isMovie) "id_movie=$id" else "slug=$realSlug"}&token=1&sk=&step=1" | ||||
| 
 | ||||
|  | @ -228,7 +226,7 @@ class LookMovieProvider : MainAPI() { | |||
|             ) | ||||
|             return MovieLoadResponse( | ||||
|                 title, | ||||
|                 slug, | ||||
|                 url, | ||||
|                 this.name, | ||||
|                 TvType.Movie, | ||||
|                 localData, | ||||
|  | @ -280,7 +278,7 @@ class LookMovieProvider : MainAPI() { | |||
| 
 | ||||
|             return TvSeriesLoadResponse( | ||||
|                 title, | ||||
|                 slug, | ||||
|                 url, | ||||
|                 this.name, | ||||
|                 TvType.TvSeries, | ||||
|                 ArrayList(episodes), | ||||
|  |  | |||
|  | @ -50,7 +50,6 @@ class MeloMovieProvider : MainAPI() { | |||
|                     TvSeriesSearchResponse( | ||||
|                         i.title, | ||||
|                         currentUrl, | ||||
|                         currentUrl, | ||||
|                         this.name, | ||||
|                         TvType.TvSeries, | ||||
|                         currentPoster, | ||||
|  | @ -63,7 +62,6 @@ class MeloMovieProvider : MainAPI() { | |||
|                     MovieSearchResponse( | ||||
|                         i.title, | ||||
|                         currentUrl, | ||||
|                         currentUrl, | ||||
|                         this.name, | ||||
|                         TvType.Movie, | ||||
|                         currentUrl, | ||||
|  | @ -116,8 +114,8 @@ class MeloMovieProvider : MainAPI() { | |||
|         return true | ||||
|     } | ||||
| 
 | ||||
|     override fun load(slug: String): LoadResponse? { | ||||
|         val response = khttp.get(slug).text | ||||
|     override fun load(url: String): LoadResponse? { | ||||
|         val response = khttp.get(url).text | ||||
| 
 | ||||
|         //backdrop = imgurl | ||||
|         fun findUsingRegex(src: String): String? { | ||||
|  | @ -137,7 +135,7 @@ class MeloMovieProvider : MainAPI() { | |||
|             val serialize = document.selectFirst("table.accordion__list") | ||||
|             return MovieLoadResponse( | ||||
|                 title, | ||||
|                 slug, | ||||
|                 url, | ||||
|                 this.name, | ||||
|                 TvType.Movie, | ||||
|                 serializeData(serialize), | ||||
|  | @ -164,7 +162,7 @@ class MeloMovieProvider : MainAPI() { | |||
|             episodes.reverse() | ||||
|             return TvSeriesLoadResponse( | ||||
|                 title, | ||||
|                 slug, | ||||
|                 url, | ||||
|                 this.name, | ||||
|                 TvType.TvSeries, | ||||
|                 episodes, | ||||
|  |  | |||
|  | @ -40,7 +40,6 @@ class TrailersToProvider : MainAPI() { | |||
|                 return@mapNotNull if (isMovieType) MovieSearchResponse( | ||||
|                     name, | ||||
|                     href, | ||||
|                     href, | ||||
|                     this.name, | ||||
|                     TvType.Movie, | ||||
|                     posterUrl, | ||||
|  | @ -48,7 +47,6 @@ class TrailersToProvider : MainAPI() { | |||
|                 ) else TvSeriesSearchResponse( | ||||
|                     name, | ||||
|                     href, | ||||
|                     href, | ||||
|                     this.name, | ||||
|                     TvType.TvSeries, | ||||
|                     posterUrl, | ||||
|  | @ -84,9 +82,9 @@ class TrailersToProvider : MainAPI() { | |||
| 
 | ||||
|             returnValue.add( | ||||
|                 if (isTvShow) { | ||||
|                     TvSeriesSearchResponse(name, href, href, this.name, TvType.TvSeries, poster, year, null) | ||||
|                     TvSeriesSearchResponse(name, href, this.name, TvType.TvSeries, poster, year, null) | ||||
|                 } else { | ||||
|                     MovieSearchResponse(name, href, href, this.name, TvType.Movie, poster, year) | ||||
|                     MovieSearchResponse(name, href, this.name, TvType.Movie, poster, year) | ||||
|                 } | ||||
|             ) | ||||
|         } | ||||
|  | @ -111,9 +109,9 @@ class TrailersToProvider : MainAPI() { | |||
| 
 | ||||
|             returnValue.add( | ||||
|                 if (isTvShow) { | ||||
|                     TvSeriesSearchResponse(name, href, href, this.name, TvType.TvSeries, poster, year, null) | ||||
|                     TvSeriesSearchResponse(name, href, this.name, TvType.TvSeries, poster, year, null) | ||||
|                 } else { | ||||
|                     MovieSearchResponse(name, href, href, this.name, TvType.Movie, poster, year) | ||||
|                     MovieSearchResponse(name, href, this.name, TvType.Movie, poster, year) | ||||
|                 } | ||||
|             ) | ||||
|         } | ||||
|  |  | |||
|  | @ -9,12 +9,13 @@ import com.lagradost.cloudstream3.utils.ExtractorLink | |||
| class ErrorLoadingException(message: String) : Exception(message) | ||||
| 
 | ||||
| class APIRepository(val api: MainAPI) { | ||||
|     val name : String get() = api.name | ||||
|     val mainUrl : String get() = api.mainUrl | ||||
|     val name: String get() = api.name | ||||
|     val mainUrl: String get() = api.mainUrl | ||||
| 
 | ||||
|     suspend fun load(url: String): Resource<LoadResponse> { | ||||
|         return safeApiCall { | ||||
|             api.load(url) ?: throw ErrorLoadingException("Error Loading") | ||||
|             // remove suffix for some slugs to handle correctly | ||||
|             api.load(url.removeSuffix("/")) ?: throw ErrorLoadingException("Error Loading") | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -143,11 +143,10 @@ fun ResultEpisode.getWatchProgress(): Float { | |||
| 
 | ||||
| class ResultFragment : Fragment() { | ||||
|     companion object { | ||||
|         fun newInstance(url: String, slug: String, apiName: String, startAction: Int = 0) = | ||||
|         fun newInstance(url: String, apiName: String, startAction: Int = 0) = | ||||
|             ResultFragment().apply { | ||||
|                 arguments = Bundle().apply { | ||||
|                     putString("url", url) | ||||
|                     putString("slug", slug) | ||||
|                     putString("apiName", apiName) | ||||
|                     putInt("startAction", startAction) | ||||
|                 } | ||||
|  | @ -257,7 +256,6 @@ class ResultFragment : Fragment() { | |||
|         // activity?.fixPaddingStatusbar(result_toolbar) | ||||
| 
 | ||||
|         url = arguments?.getString("url") | ||||
|         val slug = arguments?.getString("slug") | ||||
|         val apiName = arguments?.getString("apiName") ?: return | ||||
|         startAction = arguments?.getInt("startAction") ?: START_ACTION_NORMAL | ||||
| 
 | ||||
|  | @ -431,7 +429,6 @@ class ResultFragment : Fragment() { | |||
|                         VideoDownloadHelper.DownloadHeaderCached( | ||||
|                             apiName, | ||||
|                             url ?: return@let, | ||||
|                             slug ?: return@let, | ||||
|                             currentType ?: return@let, | ||||
|                             currentHeaderName ?: return@let, | ||||
|                             currentPoster ?: return@let, | ||||
|  | @ -986,21 +983,20 @@ class ResultFragment : Fragment() { | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (apiName != null && slug != null) { | ||||
|         val tempUrl = url | ||||
|         if (tempUrl != null) { | ||||
|             result_reload_connectionerror.setOnClickListener { | ||||
|                 viewModel.load(requireContext(), slug, apiName) | ||||
|                 viewModel.load(requireContext(), tempUrl, apiName) | ||||
|             } | ||||
| 
 | ||||
|             if (url != null) { | ||||
|                 result_reload_connection_open_in_browser.setOnClickListener { | ||||
|                     val i = Intent(ACTION_VIEW) | ||||
|                     i.data = Uri.parse(url) | ||||
|                     startActivity(i) | ||||
|                 } | ||||
|             result_reload_connection_open_in_browser.setOnClickListener { | ||||
|                 val i = Intent(ACTION_VIEW) | ||||
|                 i.data = Uri.parse(tempUrl) | ||||
|                 startActivity(i) | ||||
|             } | ||||
| 
 | ||||
|             if (viewModel.resultResponse.value == null) | ||||
|                 viewModel.load(requireContext(), slug, apiName) | ||||
|                 viewModel.load(requireContext(), tempUrl, apiName) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -9,9 +9,11 @@ import com.lagradost.cloudstream3.mvvm.Resource | |||
| import com.lagradost.cloudstream3.mvvm.safeApiCall | ||||
| import com.lagradost.cloudstream3.ui.APIRepository | ||||
| import com.lagradost.cloudstream3.ui.WatchType | ||||
| import com.lagradost.cloudstream3.utils.DataStoreHelper | ||||
| import com.lagradost.cloudstream3.utils.DataStoreHelper.getResultSeason | ||||
| import com.lagradost.cloudstream3.utils.DataStoreHelper.getResultWatchState | ||||
| import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos | ||||
| import com.lagradost.cloudstream3.utils.DataStoreHelper.setBookmarkedData | ||||
| import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultSeason | ||||
| import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultWatchState | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
|  | @ -21,7 +23,7 @@ const val EPISODE_RANGE_SIZE = 50 | |||
| const val EPISODE_RANGE_OVERLOAD = 60 | ||||
| 
 | ||||
| class ResultViewModel : ViewModel() { | ||||
|     var repo : APIRepository? = null | ||||
|     var repo: APIRepository? = null | ||||
| 
 | ||||
|     private val _resultResponse: MutableLiveData<Resource<Any?>> = MutableLiveData() | ||||
|     private val _episodes: MutableLiveData<List<ResultEpisode>> = MutableLiveData() | ||||
|  | @ -51,6 +53,21 @@ class ResultViewModel : ViewModel() { | |||
|         val currentId = id.value ?: return | ||||
|         _watchStatus.postValue(status) | ||||
|         context.setResultWatchState(currentId, status.internalId) | ||||
|         val resultPage = page.value | ||||
|         if (resultPage != null) { | ||||
|             context.setBookmarkedData( | ||||
|                 currentId, | ||||
|                 DataStoreHelper.BookmarkedData( | ||||
|                     currentId, | ||||
|                     resultPage.name, | ||||
|                     resultPage.url, | ||||
|                     resultPage.apiName, | ||||
|                     resultPage.type, | ||||
|                     resultPage.posterUrl, | ||||
|                     resultPage.year | ||||
|                 ) | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private fun loadWatchStatus(context: Context, localId: Int? = null) { | ||||
|  | @ -154,80 +171,78 @@ class ResultViewModel : ViewModel() { | |||
|         when (data) { | ||||
|             is Resource.Success -> { | ||||
|                 val d = data.value | ||||
|                 if (d is LoadResponse) { | ||||
|                     page.postValue(d) | ||||
|                     val mainId = d.getId() | ||||
|                     id.postValue(mainId) | ||||
|                     loadWatchStatus(context, mainId) | ||||
|                 page.postValue(d) | ||||
|                 val mainId = d.getId() | ||||
|                 id.postValue(mainId) | ||||
|                 loadWatchStatus(context, mainId) | ||||
| 
 | ||||
|                     when (d) { | ||||
|                         is AnimeLoadResponse -> { | ||||
|                             val isDub = d.dubEpisodes != null && d.dubEpisodes.size > 0 | ||||
|                             dubStatus.postValue(if (isDub) DubStatus.Dubbed else DubStatus.Subbed) | ||||
|                 when (d) { | ||||
|                     is AnimeLoadResponse -> { | ||||
|                         val isDub = d.dubEpisodes != null && d.dubEpisodes.size > 0 | ||||
|                         dubStatus.postValue(if (isDub) DubStatus.Dubbed else DubStatus.Subbed) | ||||
| 
 | ||||
|                             val dataList = (if (isDub) d.dubEpisodes else d.subEpisodes) | ||||
|                         val dataList = (if (isDub) d.dubEpisodes else d.subEpisodes) | ||||
| 
 | ||||
|                             if (dataList != null) { | ||||
|                                 val episodes = ArrayList<ResultEpisode>() | ||||
|                                 for ((index, i) in dataList.withIndex()) { | ||||
|                                     episodes.add( | ||||
|                                         context.buildResultEpisode( | ||||
|                                             i.name, | ||||
|                                             i.posterUrl, | ||||
|                                             index + 1, //TODO MAKE ABLE TO NOT HAVE SOME EPISODE | ||||
|                                             null, // TODO FIX SEASON | ||||
|                                             i.url, | ||||
|                                             apiName, | ||||
|                                             (mainId + index + 1), | ||||
|                                             index, | ||||
|                                             i.rating, | ||||
|                                             i.descript, | ||||
|                                         ) | ||||
|                                     ) | ||||
|                                 } | ||||
|                                 updateEpisodes(context, mainId, episodes, -1) | ||||
|                             } | ||||
|                         } | ||||
| 
 | ||||
|                         is TvSeriesLoadResponse -> { | ||||
|                         if (dataList != null) { | ||||
|                             val episodes = ArrayList<ResultEpisode>() | ||||
|                             for ((index, i) in d.episodes.withIndex()) { | ||||
|                             for ((index, i) in dataList.withIndex()) { | ||||
|                                 episodes.add( | ||||
|                                     context.buildResultEpisode( | ||||
|                                         i.name, | ||||
|                                         //?: (if (i.season != null && i.episode != null) "S${i.season}:E${i.episode}" else null)), // TODO ADD NAMES | ||||
|                                         i.posterUrl, | ||||
|                                         i.episode ?: (index + 1), | ||||
|                                         i.season, | ||||
|                                         i.data, | ||||
|                                         index + 1, //TODO MAKE ABLE TO NOT HAVE SOME EPISODE | ||||
|                                         null, // TODO FIX SEASON | ||||
|                                         i.url, | ||||
|                                         apiName, | ||||
|                                         (mainId + index + 1).hashCode(), | ||||
|                                         (mainId + index + 1), | ||||
|                                         index, | ||||
|                                         i.rating, | ||||
|                                         i.descript | ||||
|                                         i.descript, | ||||
|                                     ) | ||||
|                                 ) | ||||
|                             } | ||||
|                             updateEpisodes(context, mainId, episodes, -1) | ||||
|                         } | ||||
|                         is MovieLoadResponse -> { | ||||
|                             updateEpisodes( | ||||
|                                 context, mainId, arrayListOf( | ||||
|                                     context.buildResultEpisode( | ||||
|                                         d.name, | ||||
|                                         null, | ||||
|                                         0, | ||||
|                                         null, | ||||
|                                         d.dataUrl, | ||||
|                                         d.apiName, | ||||
|                                         (mainId), // HAS SAME ID | ||||
|                                         0, | ||||
|                                         null, | ||||
|                                         null, | ||||
|                                     ) | ||||
|                                 ), -1 | ||||
|                     } | ||||
| 
 | ||||
|                     is TvSeriesLoadResponse -> { | ||||
|                         val episodes = ArrayList<ResultEpisode>() | ||||
|                         for ((index, i) in d.episodes.withIndex()) { | ||||
|                             episodes.add( | ||||
|                                 context.buildResultEpisode( | ||||
|                                     i.name, | ||||
|                                     //?: (if (i.season != null && i.episode != null) "S${i.season}:E${i.episode}" else null)), // TODO ADD NAMES | ||||
|                                     i.posterUrl, | ||||
|                                     i.episode ?: (index + 1), | ||||
|                                     i.season, | ||||
|                                     i.data, | ||||
|                                     apiName, | ||||
|                                     (mainId + index + 1).hashCode(), | ||||
|                                     index, | ||||
|                                     i.rating, | ||||
|                                     i.descript | ||||
|                                 ) | ||||
|                             ) | ||||
|                         } | ||||
|                         updateEpisodes(context, mainId, episodes, -1) | ||||
|                     } | ||||
|                     is MovieLoadResponse -> { | ||||
|                         updateEpisodes( | ||||
|                             context, mainId, arrayListOf( | ||||
|                                 context.buildResultEpisode( | ||||
|                                     d.name, | ||||
|                                     null, | ||||
|                                     0, | ||||
|                                     null, | ||||
|                                     d.dataUrl, | ||||
|                                     d.apiName, | ||||
|                                     (mainId), // HAS SAME ID | ||||
|                                     0, | ||||
|                                     null, | ||||
|                                     null, | ||||
|                                 ) | ||||
|                             ), -1 | ||||
|                         ) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | @ -303,8 +318,4 @@ class ResultViewModel : ViewModel() { | |||
|             val localData = loadEpisode(id, data, isCasting) | ||||
|             callback.invoke(localData) | ||||
|         } | ||||
| 
 | ||||
|     fun loadIndex(index: Int): ResultEpisode? { | ||||
|         return episodes.value?.get(index) | ||||
|     } | ||||
| } | ||||
|  | @ -142,7 +142,7 @@ class SearchFragment : Fragment() { | |||
|                     search_loading_bar.alpha = 0f | ||||
|                 } | ||||
|                 is Resource.Failure -> { | ||||
|                     Toast.makeText(activity, "Server error", Toast.LENGTH_LONG).show() | ||||
|                    // Toast.makeText(activity, "Server error", Toast.LENGTH_LONG).show() | ||||
|                     searchExitIcon.alpha = 1f | ||||
|                     search_loading_bar.alpha = 0f | ||||
|                 } | ||||
|  |  | |||
|  | @ -43,18 +43,18 @@ object AppUtils { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fun AppCompatActivity.loadResult(url: String, slug: String, apiName: String, startAction: Int = 0) { | ||||
|     fun AppCompatActivity.loadResult(url: String, apiName: String, startAction: Int = 0) { | ||||
|         this.runOnUiThread { | ||||
|             viewModelStore.clear() | ||||
|             this.supportFragmentManager.beginTransaction() | ||||
|                 .setCustomAnimations(R.anim.enter_anim, R.anim.exit_anim, R.anim.pop_enter, R.anim.pop_exit) | ||||
|                 .add(R.id.homeRoot, ResultFragment.newInstance(url, slug, apiName, startAction)) | ||||
|                 .add(R.id.homeRoot, ResultFragment.newInstance(url, apiName, startAction)) | ||||
|                 .commit() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fun Activity?.loadSearchResult(card: SearchResponse, startAction: Int = 0) { | ||||
|         (this as AppCompatActivity?)?.loadResult(card.url, card.slug, card.apiName, startAction) | ||||
|         (this as AppCompatActivity?)?.loadResult(card.url, card.apiName, startAction) | ||||
|     } | ||||
| 
 | ||||
|     fun Activity.requestLocalAudioFocus(focusRequest: AudioFocusRequest?) { | ||||
|  |  | |||
|  | @ -1,17 +1,21 @@ | |||
| package com.lagradost.cloudstream3.utils | ||||
| 
 | ||||
| import android.content.Context | ||||
| import com.lagradost.cloudstream3.SearchResponse | ||||
| import com.lagradost.cloudstream3.TvType | ||||
| import com.lagradost.cloudstream3.ui.WatchType | ||||
| import com.lagradost.cloudstream3.utils.DataStore.getKey | ||||
| import com.lagradost.cloudstream3.utils.DataStore.setKey | ||||
| 
 | ||||
| const val VIDEO_POS_DUR = "video_pos_dur" | ||||
| const val RESULT_WATCH_STATE = "result_watch_state" | ||||
| const val RESULT_WATCH_STATE_DATA = "result_watch_state_data" | ||||
| const val RESULT_SEASON = "result_season" | ||||
| 
 | ||||
| 
 | ||||
| object DataStoreHelper { | ||||
|     data class PosDur(val position: Long, val duration: Long) | ||||
| 
 | ||||
|     fun PosDur.fixVisual(): PosDur { | ||||
|         if (duration <= 0) return PosDur(0, duration) | ||||
|         val percentage = position * 100 / duration | ||||
|  | @ -21,8 +25,28 @@ object DataStoreHelper { | |||
|         return this | ||||
|     } | ||||
| 
 | ||||
|     data class BookmarkedData( | ||||
|         val parentId: Int, | ||||
|         override val name: String, | ||||
|         override val url: String, | ||||
|         override val apiName: String, | ||||
|         override val type: TvType, | ||||
|         override val posterUrl: String?, | ||||
|         override val year: Int?, | ||||
|     ) : SearchResponse | ||||
| 
 | ||||
|     var currentAccount: String = "0" //TODO ACCOUNT IMPLEMENTATION | ||||
| 
 | ||||
|     fun Context.setBookmarkedData(id: Int?, data: BookmarkedData) { | ||||
|         if (id == null) return | ||||
|         setKey("$currentAccount/$RESULT_WATCH_STATE", id.toString(), data) | ||||
|     } | ||||
| 
 | ||||
|     fun Context.getBookmarkedData(id: Int?): BookmarkedData? { | ||||
|         if (id == null) return null | ||||
|         return getKey("$currentAccount/$RESULT_WATCH_STATE", id.toString()) | ||||
|     } | ||||
| 
 | ||||
|     fun Context.setViewPos(id: Int?, pos: Long, dur: Long) { | ||||
|         if (id == null) return | ||||
|         setKey("$currentAccount/$VIDEO_POS_DUR", id.toString(), PosDur(pos, dur)) | ||||
|  | @ -44,7 +68,8 @@ object DataStoreHelper { | |||
|     fun Context.getResultSeason(id: Int): Int { | ||||
|         return getKey("$currentAccount/$RESULT_SEASON", id.toString(), -1)!! | ||||
|     } | ||||
|     fun Context.setResultSeason(id: Int, value : Int?) { | ||||
| 
 | ||||
|     fun Context.setResultSeason(id: Int, value: Int?) { | ||||
|         return setKey("$currentAccount/$RESULT_SEASON", id.toString(), value) | ||||
|     } | ||||
| } | ||||
|  | @ -2,7 +2,6 @@ package com.lagradost.cloudstream3.utils | |||
| 
 | ||||
| import com.lagradost.cloudstream3.extractors.* | ||||
| import com.lagradost.cloudstream3.mvvm.normalSafeApiCall | ||||
| import com.lagradost.cloudstream3.utils.extractors.* | ||||
| 
 | ||||
| data class ExtractorLink( | ||||
|     val source: String, | ||||
|  |  | |||
|  | @ -17,7 +17,6 @@ object VideoDownloadHelper { | |||
|     data class DownloadHeaderCached( | ||||
|         val apiName: String, | ||||
|         val url: String, | ||||
|         val slug : String, | ||||
|         val type : TvType, | ||||
|         val name: String, | ||||
|         val poster: String?, | ||||
|  |  | |||
							
								
								
									
										5
									
								
								app/src/main/res/drawable/ic_baseline_filter_list_24.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								app/src/main/res/drawable/ic_baseline_filter_list_24.xml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | |||
| <vector android:height="24dp" android:tint="#FFFFFF" | ||||
|     android:viewportHeight="24" android:viewportWidth="24" | ||||
|     android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <path android:fillColor="@android:color/white" android:pathData="M10,18h4v-2h-4v2zM3,6v2h18L21,6L3,6zM6,13h12v-2L6,11v2z"/> | ||||
| </vector> | ||||
|  | @ -87,6 +87,7 @@ | |||
|             android:id="@+id/home_loaded" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="match_parent"> | ||||
| 
 | ||||
|         <LinearLayout | ||||
|                 android:orientation="vertical" | ||||
|                 android:layout_width="match_parent" | ||||
|  | @ -202,6 +203,57 @@ | |||
|                     </ImageView> | ||||
|                 </LinearLayout> | ||||
|             </LinearLayout> | ||||
| 
 | ||||
|             <LinearLayout | ||||
|                     android:id="@+id/home_bookmarked_holder" | ||||
|                     android:orientation="vertical" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="wrap_content"> | ||||
| 
 | ||||
|                 <FrameLayout | ||||
|                         android:foreground="?android:attr/selectableItemBackgroundBorderless" | ||||
|                         android:id="@+id/home_bookmarked_child_more_info" | ||||
|                         android:padding="12dp" | ||||
|                         android:layout_width="match_parent" | ||||
|                         android:layout_height="wrap_content"> | ||||
|                     <ImageView | ||||
|                             android:src="@drawable/ic_baseline_filter_list_24" | ||||
|                             android:layout_width="24dp" | ||||
|                             android:layout_height="24dp" | ||||
|                             android:contentDescription="@string/filter_bookmarks"> | ||||
|                     </ImageView> | ||||
|                     <TextView | ||||
|                             android:layout_gravity="center_vertical" | ||||
|                             android:layout_marginStart="40dp" | ||||
|                             android:id="@+id/home_bookmarked_parent_item_title" | ||||
|                             android:layout_width="wrap_content" | ||||
|                             android:layout_height="wrap_content" | ||||
|                             android:textColor="?attr/textColor" | ||||
|                             android:gravity="center_vertical" | ||||
|                             android:textSize="18sp" | ||||
|                             android:textStyle="bold" | ||||
|                             android:text="Bookmarked" | ||||
|                     /> | ||||
|                     <ImageView | ||||
|                             android:layout_marginEnd="5dp" | ||||
|                             android:layout_gravity="end|center_vertical" | ||||
|                             android:src="@drawable/ic_baseline_arrow_forward_24" | ||||
|                             android:layout_width="30dp" | ||||
|                             android:layout_height="match_parent" | ||||
|                             android:contentDescription="@string/home_more_info"> | ||||
|                     </ImageView> | ||||
|                 </FrameLayout> | ||||
| 
 | ||||
|                 <androidx.recyclerview.widget.RecyclerView | ||||
|                         app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" | ||||
|                         android:id="@+id/home_bookmarked_child_recyclerview" | ||||
|                         android:orientation="horizontal" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         tools:listitem="@layout/home_result_grid" | ||||
|                 /> | ||||
|             </LinearLayout> | ||||
| 
 | ||||
|             <androidx.recyclerview.widget.RecyclerView | ||||
|                     android:id="@+id/home_master_recycler" | ||||
|                     android:layout_width="match_parent" | ||||
|  | @ -210,5 +262,4 @@ | |||
|             /> | ||||
|         </LinearLayout> | ||||
|     </androidx.core.widget.NestedScrollView> | ||||
| 
 | ||||
| </FrameLayout> | ||||
|  | @ -108,6 +108,7 @@ | |||
|         </com.google.android.material.appbar.AppBarLayout> | ||||
| 
 | ||||
|         <FrameLayout | ||||
|                 android:visibility="gone" | ||||
|                 android:alpha="0" | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:id="@+id/result_poster_blur_holder" | ||||
|  | @ -120,10 +121,13 @@ | |||
|                     tools:src="@drawable/example_poster" | ||||
|                     android:background="@color/darkBackground" | ||||
|                     android:id="@+id/result_poster_blur" | ||||
|                     android:contentDescription=""/> | ||||
|             <ImageView android:src="@drawable/background_shadow" android:layout_gravity="bottom" | ||||
|                        android:layout_width="match_parent" android:layout_height="30dp"> | ||||
| 
 | ||||
|                     android:contentDescription="@string/background_blur"/> | ||||
|             <ImageView | ||||
|                     android:src="@drawable/background_shadow" | ||||
|                     android:layout_gravity="bottom" | ||||
|                     android:layout_width="match_parent" | ||||
|                     android:layout_height="30dp" | ||||
|                     android:contentDescription="@string/background_shadow"> | ||||
|             </ImageView> | ||||
|         </FrameLayout> | ||||
|         <androidx.core.widget.NestedScrollView | ||||
|  | @ -163,13 +167,13 @@ | |||
| 
 | ||||
| 
 | ||||
|                     <LinearLayout | ||||
|                             android:layout_marginLeft="10dp" | ||||
|                             android:layout_marginStart="10dp" | ||||
|                             android:gravity="center_vertical" | ||||
|                             android:orientation="vertical" | ||||
|                             android:layout_width="wrap_content" | ||||
|                             android:layout_height="wrap_content"> | ||||
|                         <TextView | ||||
|                                 android:layout_marginRight="50dp" | ||||
|                                 android:layout_marginEnd="50dp" | ||||
|                                 tools:text="The Perfect Run The Perfect Run The Perfect Run" | ||||
|                                 android:id="@+id/result_title" | ||||
|                                 android:textSize="20sp" | ||||
|  | @ -201,7 +205,6 @@ | |||
|                         android:layout_width="match_parent" | ||||
|                         android:layout_height="50dp"> | ||||
|                     <com.google.android.material.button.MaterialButton | ||||
|                             android:visibility="gone" | ||||
|                             android:layout_gravity="center_vertical" | ||||
|                             app:cornerRadius="4dp" | ||||
|                             android:id="@+id/result_bookmark_button" | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ | |||
|         xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|         xmlns:tools="http://schemas.android.com/tools" | ||||
|         android:orientation="vertical" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="wrap_content"> | ||||
| 
 | ||||
|     <FrameLayout | ||||
|  | @ -36,7 +36,7 @@ | |||
|             app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" | ||||
|             android:id="@+id/home_child_recyclerview" | ||||
|             android:orientation="horizontal" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             tools:listitem="@layout/home_result_grid" | ||||
|     /> | ||||
|  |  | |||
|  | @ -61,4 +61,7 @@ | |||
|     <string name="home_info">Info</string> | ||||
|     <string name="home_next_random">Next Random</string> | ||||
|     <string name="home_change_provider">Change Provider</string> | ||||
|     <string name="background_blur">Background blur</string> | ||||
|     <string name="background_shadow">Background Shadow</string> | ||||
|     <string name="filter_bookmarks">Filter Bookmarks</string> | ||||
| </resources> | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue