forked from recloudstream/cloudstream
		
	experimental inf homepage (9anime test)
This commit is contained in:
		
							parent
							
								
									334af5acfb
								
							
						
					
					
						commit
						e64c84500d
					
				
					 89 changed files with 379 additions and 199 deletions
				
			
		|  | @ -376,6 +376,32 @@ data class ProvidersInfoJson( | |||
|     @JsonProperty("status") var status: Int, | ||||
| ) | ||||
| 
 | ||||
| 
 | ||||
| data class MainPageData( | ||||
|     val name: String, | ||||
|     val data: String, | ||||
| ) | ||||
| 
 | ||||
| /** return list of MainPageData with url to name, make for more readable code */ | ||||
| fun mainPageOf(vararg elements: Pair<String, String>): List<MainPageData> { | ||||
|     return elements.map { (url, name) -> MainPageData(name = name, data = url) } | ||||
| } | ||||
| 
 | ||||
| fun newHomePageResponse( | ||||
|     name: String, | ||||
|     list: List<SearchResponse>, | ||||
|     hasNext: Boolean? = null | ||||
| ): HomePageResponse { | ||||
|     return HomePageResponse( | ||||
|         listOf(HomePageList(name, list)), | ||||
|         hasNext = hasNext ?: list.isNotEmpty() | ||||
|     ) | ||||
| } | ||||
| 
 | ||||
| fun newHomePageResponse(list: HomePageList, hasNext: Boolean? = null): HomePageResponse { | ||||
|     return HomePageResponse(listOf(list), hasNext = hasNext ?: list.list.isNotEmpty()) | ||||
| } | ||||
| 
 | ||||
| /**Every provider will **not** have try catch built in, so handle exceptions when calling these functions*/ | ||||
| abstract class MainAPI { | ||||
|     companion object { | ||||
|  | @ -431,8 +457,14 @@ abstract class MainAPI { | |||
|     open val vpnStatus = VPNStatus.None | ||||
|     open val providerType = ProviderType.DirectProvider | ||||
| 
 | ||||
|     open val mainPage = listOf(MainPageData("", "")) | ||||
| 
 | ||||
|     @WorkerThread | ||||
|     open suspend fun getMainPage(): HomePageResponse? { | ||||
|     open suspend fun getMainPage( | ||||
|         page: Int, | ||||
|         categoryName: String, | ||||
|         categoryData: String | ||||
|     ): HomePageResponse? { | ||||
|         throw NotImplementedError() | ||||
|     } | ||||
| 
 | ||||
|  | @ -632,7 +664,8 @@ fun TvType.isAnimeOp(): Boolean { | |||
| data class SubtitleFile(val lang: String, val url: String) | ||||
| 
 | ||||
| data class HomePageResponse( | ||||
|     val items: List<HomePageList> | ||||
|     val items: List<HomePageList>, | ||||
|     val hasNext: Boolean = false | ||||
| ) | ||||
| 
 | ||||
| data class HomePageList( | ||||
|  |  | |||
|  | @ -104,7 +104,7 @@ class AllAnimeProvider : MainAPI() { | |||
|         @JsonProperty("__typename") val _typename: String? = null | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val urls = listOf( | ||||
| //            Pair( | ||||
|  |  | |||
|  | @ -114,7 +114,7 @@ class AniPlayProvider : MainAPI() { | |||
|         @JsonProperty("videoUrl") val url: String | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val response = app.get("$mainUrl/api/home/latest-episodes?page=0").parsed<List<ApiMainPageAnime>>() | ||||
| 
 | ||||
|         val results = response.map{ | ||||
|  |  | |||
|  | @ -45,7 +45,7 @@ class AniflixProvider : MainAPI() { | |||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val soup = app.get(mainUrl).document | ||||
|         val elements = listOf( | ||||
|  |  | |||
|  | @ -62,7 +62,7 @@ class AnimeIndoProvider : MainAPI() { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val document = request(mainUrl).document | ||||
| 
 | ||||
|         val homePageList = ArrayList<HomePageList>() | ||||
|  |  | |||
|  | @ -58,7 +58,7 @@ class AnimePaheProvider : MainAPI() { | |||
|         TvType.OVA | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         data class Data( | ||||
|             @JsonProperty("id") val id: Int, | ||||
|             @JsonProperty("anime_id") val animeId: Int, | ||||
|  |  | |||
|  | @ -47,7 +47,7 @@ class AnimeSailProvider : MainAPI() { | |||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val document = request(mainUrl).document | ||||
| 
 | ||||
|         val homePageList = ArrayList<HomePageList>() | ||||
|  |  | |||
|  | @ -64,7 +64,7 @@ class AnimeSaturnProvider : MainAPI() { | |||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val document = app.get(mainUrl).document | ||||
|         val list = ArrayList<HomePageList>() | ||||
|         document.select("div.container:has(span.badge-saturn)").forEach { | ||||
|  |  | |||
|  | @ -130,7 +130,7 @@ class AnimeWorldProvider : MainAPI() { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val document = request(mainUrl).document | ||||
|         val list = ArrayList<HomePageList>() | ||||
| 
 | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ class AnimefenixProvider:MainAPI() { | |||
|         else DubStatus.Subbed | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val urls = listOf( | ||||
|             Pair("$mainUrl/", "Animes"), | ||||
|             Pair("$mainUrl/animes?type[]=movie&order=default", "Peliculas", ), | ||||
|  |  | |||
|  | @ -22,7 +22,7 @@ class AnimeflvIOProvider:MainAPI() { | |||
|         TvType.OVA, | ||||
|         TvType.Anime, | ||||
|     ) | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val urls = listOf( | ||||
|             Pair("$mainUrl/series", "Series actualizadas",), | ||||
|  |  | |||
|  | @ -34,7 +34,7 @@ class AnimeflvnetProvider : MainAPI() { | |||
|         TvType.Anime, | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val urls = listOf( | ||||
|             Pair("$mainUrl/browse?type[]=movie&order=updated", "Películas"), | ||||
|             Pair("$mainUrl/browse?status[]=2&order=default", "Animes"), | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ class AnimekisaProvider : MainAPI() { | |||
|         @JsonProperty("html") val html: String | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val urls = listOf( | ||||
|             Pair("$mainUrl/ajax/list/views?type=all", "All animes"), | ||||
|             Pair("$mainUrl/ajax/list/views?type=day", "Trending now"), | ||||
|  |  | |||
|  | @ -96,7 +96,7 @@ class DubbedAnimeProvider : MainAPI() { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val trendingUrl = "$mainUrl/xz/trending.php?_=$unixTimeMS" | ||||
|         val lastEpisodeUrl = "$mainUrl/xz/epgrid.php?p=1&_=$unixTimeMS" | ||||
|         val recentlyAddedUrl = "$mainUrl/xz/gridgrabrecent.php?p=1&_=$unixTimeMS" | ||||
|  |  | |||
|  | @ -178,7 +178,7 @@ class GogoanimeProvider : MainAPI() { | |||
|         TvType.OVA | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val headers = mapOf( | ||||
|             "authority" to "ajax.gogo-load.com", | ||||
|             "sec-ch-ua" to "\"Google Chrome\";v=\"89\", \"Chromium\";v=\"89\", \";Not A Brand\";v=\"99\"", | ||||
|  |  | |||
|  | @ -46,7 +46,7 @@ class GomunimeProvider : MainAPI() { | |||
|         @JsonProperty("html") val html: String | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val urls = listOf( | ||||
|             Pair("e", "Episode Baru"), | ||||
|             Pair("c", "Completed"), | ||||
|  |  | |||
|  | @ -32,7 +32,7 @@ class JKAnimeProvider : MainAPI() { | |||
|         TvType.Anime, | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val urls = listOf( | ||||
|             Pair( | ||||
|                 "$mainUrl/directorio/?filtro=fecha&tipo=TV&estado=1&fecha=none&temporada=none&orden=desc", | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ class KawaiifuProvider : MainAPI() { | |||
| 
 | ||||
|     override val supportedTypes = setOf(TvType.Anime, TvType.AnimeMovie) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val resp = app.get(mainUrl).text | ||||
| 
 | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ class KimCartoonProvider : MainAPI() { | |||
|         return if (url.startsWith("/")) mainUrl + url else url | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val doc = app.get(mainUrl).document.select("#container") | ||||
|         val response = mutableListOf( | ||||
|             HomePageList( | ||||
|  |  | |||
|  | @ -38,7 +38,7 @@ class KuramanimeProvider : MainAPI() { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val document = app.get(mainUrl).document | ||||
| 
 | ||||
|         val homePageList = ArrayList<HomePageList>() | ||||
|  |  | |||
|  | @ -39,7 +39,7 @@ class KuronimeProvider : MainAPI() { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val document = app.get(mainUrl).document | ||||
| 
 | ||||
|         val homePageList = ArrayList<HomePageList>() | ||||
|  |  | |||
|  | @ -34,7 +34,7 @@ class MonoschinosProvider : MainAPI() { | |||
|         TvType.Anime, | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val urls = listOf( | ||||
|             Pair("$mainUrl/emision", "En emisión"), | ||||
|             Pair( | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ class MundoDonghuaProvider : MainAPI() { | |||
|         TvType.Anime, | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val urls = listOf( | ||||
|             Pair("$mainUrl/lista-donghuas", "Donghuas"), | ||||
|         ) | ||||
|  |  | |||
|  | @ -40,7 +40,7 @@ class NeonimeProvider : MainAPI() { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val document = app.get(mainUrl).document | ||||
| 
 | ||||
|         val homePageList = ArrayList<HomePageList>() | ||||
|  |  | |||
|  | @ -137,44 +137,45 @@ class NineAnimeProvider : MainAPI() { | |||
|         private fun decode(input: String): String = java.net.URLDecoder.decode(input, "utf-8") | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|         val items = listOf( | ||||
|             "$mainUrl/ajax/home/widget/trending?page=1" to "Trending", | ||||
|             "$mainUrl/ajax/home/widget/updated-all?page=1" to "All", | ||||
|             "$mainUrl/ajax/home/widget/updated-sub?page=1" to "Recently Updated (SUB)", | ||||
|             "$mainUrl/ajax/home/widget/updated-dub?page=1" to | ||||
|                     "Recently Updated (DUB)", | ||||
|             "$mainUrl/ajax/home/widget/updated-china?page=1" to | ||||
|                     "Recently Updated (Chinese)", | ||||
|             "$mainUrl/ajax/home/widget/random?page=1" to "Random", | ||||
|         ).apmap { (url, name) -> | ||||
|             val home = Jsoup.parse( | ||||
|                 app.get( | ||||
|                     url | ||||
|                 ).parsed<Response>().html | ||||
|             ).select("div.item").mapNotNull { element -> | ||||
|                 val title = element.selectFirst(".info > .name") ?: return@mapNotNull null | ||||
|                 val link = title.attr("href") | ||||
|                 val poster = element.selectFirst(".poster > a > img")?.attr("src") | ||||
|                 val meta = element.selectFirst(".poster > a > .meta > .inner > .left") | ||||
|                 val subbedEpisodes = meta?.selectFirst(".sub")?.text()?.toIntOrNull() | ||||
|                 val dubbedEpisodes = meta?.selectFirst(".dub")?.text()?.toIntOrNull() | ||||
|     override val mainPage = mainPageOf( | ||||
|         "$mainUrl/ajax/home/widget/trending?page=" to "Trending", | ||||
|         "$mainUrl/ajax/home/widget/updated-all?page=" to "All", | ||||
|         "$mainUrl/ajax/home/widget/updated-sub?page=" to "Recently Updated (SUB)", | ||||
|         "$mainUrl/ajax/home/widget/updated-dub?page=" to "Recently Updated (DUB)", | ||||
|         "$mainUrl/ajax/home/widget/updated-china?page=" to "Recently Updated (Chinese)", | ||||
|         "$mainUrl/ajax/home/widget/random?page=" to "Random", | ||||
|     ) | ||||
| 
 | ||||
|                 newAnimeSearchResponse(title.text() ?: return@mapNotNull null, link) { | ||||
|                     this.posterUrl = poster | ||||
|                     addDubStatus( | ||||
|                         dubbedEpisodes != null, | ||||
|                         subbedEpisodes != null, | ||||
|                         dubbedEpisodes, | ||||
|                         subbedEpisodes | ||||
|                     ) | ||||
|                 } | ||||
|     override suspend fun getMainPage( | ||||
|         page: Int, | ||||
|         categoryName: String, | ||||
|         categoryData: String | ||||
|     ): HomePageResponse { | ||||
|         val url = categoryData + page | ||||
|         val home = Jsoup.parse( | ||||
|             app.get( | ||||
|                 url | ||||
|             ).parsed<Response>().html | ||||
|         ).select("div.item").mapNotNull { element -> | ||||
|             val title = element.selectFirst(".info > .name") ?: return@mapNotNull null | ||||
|             val link = title.attr("href") | ||||
|             val poster = element.selectFirst(".poster > a > img")?.attr("src") | ||||
|             val meta = element.selectFirst(".poster > a > .meta > .inner > .left") | ||||
|             val subbedEpisodes = meta?.selectFirst(".sub")?.text()?.toIntOrNull() | ||||
|             val dubbedEpisodes = meta?.selectFirst(".dub")?.text()?.toIntOrNull() | ||||
| 
 | ||||
|             newAnimeSearchResponse(title.text() ?: return@mapNotNull null, link) { | ||||
|                 this.posterUrl = poster | ||||
|                 addDubStatus( | ||||
|                     dubbedEpisodes != null, | ||||
|                     subbedEpisodes != null, | ||||
|                     dubbedEpisodes, | ||||
|                     subbedEpisodes | ||||
|                 ) | ||||
|             } | ||||
| 
 | ||||
|             HomePageList(name, home) | ||||
|         } | ||||
| 
 | ||||
|         return HomePageResponse(items) | ||||
|         return newHomePageResponse(categoryName, home) | ||||
|     } | ||||
| 
 | ||||
|     data class Response( | ||||
|  |  | |||
|  | @ -40,7 +40,7 @@ class NontonAnimeIDProvider : MainAPI() { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val document = app.get(mainUrl).document | ||||
| 
 | ||||
|         val homePageList = ArrayList<HomePageList>() | ||||
|  |  | |||
|  | @ -40,7 +40,7 @@ class OploverzProvider : MainAPI() { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val document = app.get(mainUrl).document | ||||
| 
 | ||||
|         val homePageList = ArrayList<HomePageList>() | ||||
|  |  | |||
|  | @ -38,7 +38,7 @@ class OtakudesuProvider : MainAPI() { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val document = app.get(mainUrl).document | ||||
| 
 | ||||
|         val homePageList = ArrayList<HomePageList>() | ||||
|  |  | |||
|  | @ -44,7 +44,7 @@ class TenshiProvider : MainAPI() { | |||
|         } | ||||
|     }*/ | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val soup = app.get(mainUrl, interceptor = ddosGuardKiller).document | ||||
|         for (section in soup.select("#content > section")) { | ||||
|  |  | |||
|  | @ -39,7 +39,7 @@ class TocanimeProvider : MainAPI() { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val document = app.get(mainUrl).document | ||||
| 
 | ||||
|         val homePageList = ArrayList<HomePageList>() | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ class WcoProvider : MainAPI() { | |||
|         TvType.OVA | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val urls = listOf( | ||||
|             Pair("$mainUrl/ajax/list/recently_updated?type=tv", "Recently Updated Anime"), | ||||
|             Pair("$mainUrl/ajax/list/recently_updated?type=movie", "Recently Updated Movies"), | ||||
|  |  | |||
|  | @ -77,7 +77,7 @@ class ZoroProvider : MainAPI() { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val html = app.get("$mainUrl/home").text | ||||
|         val document = Jsoup.parse(html) | ||||
| 
 | ||||
|  |  | |||
|  | @ -37,7 +37,7 @@ class EjaTv : MainAPI() { | |||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         // Maybe this based on app language or as setting? | ||||
|         val language = "English" | ||||
|         val dataMap = mapOf( | ||||
|  |  | |||
|  | @ -196,7 +196,7 @@ open class TmdbProvider : MainAPI() { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
| 
 | ||||
|         // SAME AS DISCOVER IT SEEMS | ||||
| //        val popularSeries = tmdb.tvService().popular(1, "en-US").execute().body()?.results?.map { | ||||
|  |  | |||
|  | @ -34,7 +34,7 @@ class AkwamProvider : MainAPI() { | |||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         // Title, Url | ||||
|         val moviesUrl = listOf( | ||||
|             "Movies" to "$mainUrl/movies", | ||||
|  |  | |||
|  | @ -27,7 +27,7 @@ class AllMoviesForYouProvider : MainAPI() { | |||
|         TvType.TvSeries | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val soup = app.get(mainUrl).document | ||||
|         val urls = listOf( | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ class AltadefinizioneProvider : MainAPI() { | |||
|         TvType.Movie | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val urls = listOf( | ||||
|             Pair("$mainUrl/azione/", "Azione"), | ||||
|  |  | |||
|  | @ -110,7 +110,7 @@ class AsiaFlixProvider : MainAPI() { | |||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val headers = mapOf("X-Requested-By" to "asiaflix-web") | ||||
|         val response = app.get("$apiUrl/dashboard", headers = headers).text | ||||
| 
 | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ open class BflixProvider : MainAPI() { | |||
| 
 | ||||
|     //override val uniqueId: Int by lazy { "BflixProvider".hashCode() } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val soup = app.get("$mainUrl/home").document | ||||
|         val testa = listOf( | ||||
|  |  | |||
|  | @ -41,7 +41,7 @@ class CimaNowProvider : MainAPI() { | |||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
| 
 | ||||
|         val doc = app.get("$mainUrl/home", headers = mapOf("user-agent" to "MONKE")).document | ||||
|         val pages = doc.select("section").not("section:contains(أختر وجهتك المفضلة)").not("section:contains(تم اضافته حديثاً)").apmap { | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ class CineblogProvider : MainAPI() { | |||
|         TvType.TvSeries, | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val urls = listOf( | ||||
|             Pair("$mainUrl/genere/azione/", "Azione"), | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ class CinecalidadProvider : MainAPI() { | |||
|     ) | ||||
|     override val vpnStatus = VPNStatus.MightBeNeeded //Due to evoload sometimes not loading | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val urls = listOf( | ||||
|             Pair("$mainUrl/ver-serie/", "Series"), | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ class CuevanaProvider : MainAPI() { | |||
|         TvType.TvSeries, | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val urls = listOf( | ||||
|             Pair(mainUrl, "Recientemente actualizadas"), | ||||
|  |  | |||
|  | @ -31,7 +31,7 @@ class DoramasYTProvider : MainAPI() { | |||
|         TvType.AsianDrama, | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val urls = listOf( | ||||
|             Pair("$mainUrl/emision", "En emisión"), | ||||
|             Pair( | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ class DramaSeeProvider : MainAPI() { | |||
|     override val hasDownloadSupport = true | ||||
|     override val supportedTypes = setOf(TvType.AsianDrama) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val headers = mapOf("X-Requested-By" to mainUrl) | ||||
|         val document = app.get(mainUrl, headers = headers).document | ||||
|         val mainbody = document.getElementsByTag("body") | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ class DramaidProvider : MainAPI() { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val document = app.get(mainUrl).document | ||||
| 
 | ||||
|         val homePageList = ArrayList<HomePageList>() | ||||
|  |  | |||
|  | @ -41,7 +41,7 @@ class EgyBestProvider : MainAPI() { | |||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         // url, title | ||||
|         val doc = app.get(mainUrl).document | ||||
|         val pages = arrayListOf<HomePageList>() | ||||
|  |  | |||
|  | @ -15,7 +15,7 @@ class ElifilmsProvider : MainAPI() { | |||
|         TvType.Movie, | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val newest = app.get(mainUrl).document.selectFirst("a.fav_link.premiera")?.attr("href") | ||||
|         val urls = listOf( | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ class EntrepeliculasyseriesProvider:MainAPI() { | |||
|     ) | ||||
|     override val vpnStatus = VPNStatus.MightBeNeeded //Due to evoload sometimes not loading | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val urls = listOf( | ||||
|             Pair("$mainUrl/series/", "Series"), | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ class EstrenosDoramasProvider : MainAPI() { | |||
|         TvType.AsianDrama, | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val urls = listOf( | ||||
|             Pair(mainUrl, "Últimas series"), | ||||
|             Pair("$mainUrl/category/peliculas", "Películas"), | ||||
|  |  | |||
|  | @ -35,7 +35,7 @@ class FaselHDProvider : MainAPI() { | |||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         // Title, Url | ||||
|         val moviesUrl = listOf( | ||||
|             Pair("Movies", "$mainUrl/all-movies/page/"+(0..10).random()), | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ class FilmanProvider : MainAPI() { | |||
|         TvType.TvSeries | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val document = app.get(mainUrl).document | ||||
|         val lists = document.select("#item-list,#series-list") | ||||
|         val categories = ArrayList<HomePageList>() | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ class FilmpertuttiProvider : MainAPI() { | |||
|         TvType.TvSeries | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val urls = listOf( | ||||
|             Pair("$mainUrl/category/serie-tv/", "Serie Tv"), | ||||
|  |  | |||
|  | @ -232,7 +232,7 @@ class FrenchStreamProvider : MainAPI() { | |||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse? { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse? { | ||||
|         val document = app.get(mainUrl).document | ||||
|         val docs = document.select("div.sect") | ||||
|         val returnList = docs.mapNotNull { | ||||
|  |  | |||
|  | @ -69,7 +69,7 @@ class HDMProvider : MainAPI() { | |||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val html = app.get(mainUrl, timeout = 25).text | ||||
|         val document = Jsoup.parse(html) | ||||
|         val all = ArrayList<HomePageList>() | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ class HDMovie5 : MainAPI() { | |||
|         TvType.TvSeries, | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val doc = app.get(mainUrl).document.select("div.content") | ||||
|         val list = mapOf( | ||||
|             "Featured Movies" to "featured", | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ class HDrezkaProvider : MainAPI() { | |||
|         TvType.AsianDrama | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
| 
 | ||||
|         val items = ArrayList<HomePageList>() | ||||
| 
 | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ class IHaveNoTvProvider : MainAPI() { | |||
| 
 | ||||
|     override val supportedTypes = setOf(TvType.Documentary) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         // Uhh, I am too lazy to scrape the "latest documentaries" and "recommended documentaries", | ||||
|         // so I am just scraping 3 random categories | ||||
|         val allCategories = listOf( | ||||
|  |  | |||
|  | @ -22,7 +22,7 @@ class IdlixProvider : MainAPI() { | |||
|         TvType.TvSeries, | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val document = app.get(mainUrl).document | ||||
| 
 | ||||
|         val homePageList = ArrayList<HomePageList>() | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ class KdramaHoodProvider : MainAPI() { | |||
|         @JsonProperty("file") val file: String | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val doc = app.get("$mainUrl/home2").document | ||||
|         val home = ArrayList<HomePageList>() | ||||
| 
 | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ class LayarKacaProvider : MainAPI() { | |||
|         TvType.AsianDrama | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val document = app.get(mainUrl).document | ||||
| 
 | ||||
|         val homePageList = ArrayList<HomePageList>() | ||||
|  |  | |||
|  | @ -22,7 +22,7 @@ class MultiplexProvider : MainAPI() { | |||
|         TvType.AsianDrama | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val document = app.get(mainUrl).document | ||||
| 
 | ||||
|         val homePageList = ArrayList<HomePageList>() | ||||
|  |  | |||
|  | @ -44,7 +44,7 @@ class MyCimaProvider : MainAPI() { | |||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         // Title, Url | ||||
|         val moviesUrl = listOf( | ||||
|             "Movies" to "$mainUrl/movies/page/" + (0..25).random(), | ||||
|  |  | |||
|  | @ -212,7 +212,7 @@ class NginxProvider : MainAPI() { | |||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val authHeader = | ||||
|             getAuthHeader()  // call again because it isn't reloaded if in main class and storedCredentials loads after | ||||
| 
 | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ class PeliSmartProvider: MainAPI() { | |||
|     ) | ||||
|     override val vpnStatus = VPNStatus.MightBeNeeded //Due to evoload sometimes not loading | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val urls = listOf( | ||||
|             Pair("$mainUrl/peliculas/", "Peliculas"), | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ class PelisflixProvider : MainAPI() { | |||
|         TvType.TvSeries, | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val urls = listOf( | ||||
|             Pair("$mainUrl/ver-peliculas-online-gratis-fullhdc3/", "Películas"), | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ class PelisplusHDProvider:MainAPI() { | |||
|         TvType.Movie, | ||||
|         TvType.TvSeries, | ||||
|     ) | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val document = app.get(mainUrl).document | ||||
|         val map = mapOf( | ||||
|  |  | |||
|  | @ -142,7 +142,7 @@ open class PelisplusProviderTemplate : MainAPI() { | |||
| 
 | ||||
|     // This loads the homepage, which is basically a collection of search results with labels. | ||||
|     // Optional function, but make sure to enable hasMainPage if you program this. | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val urls = homePageUrlList | ||||
|         val homePageList = ArrayList<HomePageList>() | ||||
|         // .pmap {} is used to fetch the different pages in parallel | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ class PhimmoichillProvider : MainAPI() { | |||
|         TvType.AsianDrama | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val document = app.get(mainUrl).document | ||||
| 
 | ||||
|         val homePageList = ArrayList<HomePageList>() | ||||
|  |  | |||
|  | @ -15,7 +15,7 @@ class PinoyHDXyzProvider : MainAPI() { | |||
|     override val hasMainPage = true | ||||
|     override val hasQuickSearch = false | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val all = ArrayList<HomePageList>() | ||||
|         val document = app.get(mainUrl, referer = mainUrl).document | ||||
|         val mainbody = document.getElementsByTag("body") | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ class PinoyMoviePediaProvider : MainAPI() { | |||
|     override val hasMainPage = true | ||||
|     override val hasQuickSearch = false | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val all = ArrayList<HomePageList>() | ||||
|         val document = app.get(mainUrl).document | ||||
|         val mainbody = document.getElementsByTag("body") | ||||
|  |  | |||
|  | @ -90,7 +90,7 @@ class PinoyMoviesEsProvider : MainAPI() { | |||
|         return all | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val all = ArrayList<HomePageList>() | ||||
|         val document = app.get(mainUrl).document | ||||
|         val mainbody = document.getElementsByTag("body") | ||||
|  |  | |||
|  | @ -27,7 +27,7 @@ class RebahinProvider : MainAPI() { | |||
|         TvType.AsianDrama | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val urls = listOf( | ||||
|             Pair("Featured", "xtab1"), | ||||
|             Pair("Film Terbaru", "xtab2"), | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ class SeriesflixProvider : MainAPI() { | |||
|         TvType.TvSeries, | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val urls = listOf( | ||||
|             Pair("$mainUrl/ver-series-online/", "Series"), | ||||
|  |  | |||
|  | @ -41,7 +41,7 @@ open class SflixProvider : MainAPI() { | |||
|     ) | ||||
|     override val vpnStatus = VPNStatus.None | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val html = app.get("$mainUrl/home").text | ||||
|         val document = Jsoup.parse(html) | ||||
| 
 | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ class SoaptwoDayProvider : MainAPI() { | |||
|         TvType.TvSeries, | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val urls = listOf( | ||||
|             Pair("$mainUrl/movielist/", "Movies"), | ||||
|  |  | |||
|  | @ -174,7 +174,7 @@ class StreamingcommunityProvider : MainAPI() { | |||
|         val posterMap = hashMapOf<String, String>() | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val document = app.get(mainUrl).document | ||||
|         document.select("slider-title").subList(0, 6).map { it -> | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ class TantifilmProvider : MainAPI() { | |||
|         TvType.TvSeries, | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val urls = listOf( | ||||
|             Pair("$mainUrl/watch-genre/serie-tv/", "Serie Tv"), | ||||
|  |  | |||
|  | @ -143,7 +143,7 @@ class TheFlixToProvider : MainAPI() { | |||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val doc = app.get(mainUrl).document | ||||
|         val scriptText = doc.selectFirst("script[type=application/json]")!!.data() | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ class UakinoProvider : MainAPI() { | |||
|         TvType.Anime | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val document = app.get(mainUrl).document | ||||
| 
 | ||||
|         val homePageList = ArrayList<HomePageList>() | ||||
|  |  | |||
|  | @ -210,7 +210,7 @@ open class VidstreamProviderTemplate : MainAPI() { | |||
| 
 | ||||
|     // This loads the homepage, which is basically a collection of search results with labels. | ||||
|     // Optional function, but make sure to enable hasMainPage if you program this. | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val urls = homePageUrlList | ||||
|         val homePageList = ArrayList<HomePageList>() | ||||
|         // .pmap {} is used to fetch the different pages in parallel | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ class WatchAsianProvider : MainAPI() { | |||
|     override val hasDownloadSupport = true | ||||
|     override val supportedTypes = setOf(TvType.AsianDrama) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val headers = mapOf("X-Requested-By" to mainUrl) | ||||
|         val doc = app.get(mainUrl, headers = headers).document | ||||
|         val rowPair = mutableListOf<Pair<String, String>>() | ||||
|  |  | |||
|  | @ -2,7 +2,6 @@ package com.lagradost.cloudstream3.movieproviders | |||
| 
 | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.utils.AppUtils.parseJson | ||||
| import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.Qualities | ||||
| import org.jsoup.nodes.Element | ||||
|  | @ -41,7 +40,7 @@ class XcineProvider : MainAPI() { | |||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val document = app.get(mainUrl).document | ||||
|         val sections = document.select("div.group-film") | ||||
|         return HomePageResponse(sections.mapNotNull { section -> | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ class YomoviesProvider : MainAPI() { | |||
|         TvType.TvSeries, | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|     override suspend fun getMainPage(page: Int, categoryName: String, categoryData: String): HomePageResponse { | ||||
|         val document = app.get(mainUrl).document | ||||
| 
 | ||||
|         val homePageList = ArrayList<HomePageList>() | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ import android.util.Log | |||
| import androidx.lifecycle.LifecycleOwner | ||||
| import androidx.lifecycle.LiveData | ||||
| import com.bumptech.glide.load.HttpException | ||||
| import com.lagradost.cloudstream3.BuildConfig | ||||
| import com.lagradost.cloudstream3.ErrorLoadingException | ||||
| import kotlinx.coroutines.Dispatchers | ||||
| import kotlinx.coroutines.withContext | ||||
|  | @ -11,6 +12,34 @@ import java.net.SocketTimeoutException | |||
| import java.net.UnknownHostException | ||||
| import javax.net.ssl.SSLHandshakeException | ||||
| 
 | ||||
| const val DEBUG_EXCEPTION = "THIS IS A DEBUG EXCEPTION!" | ||||
| 
 | ||||
| class DebugException(message: String) : Exception("$DEBUG_EXCEPTION\n$message") | ||||
| 
 | ||||
| inline fun debugException(message: () -> String) { | ||||
|     if (BuildConfig.DEBUG) { | ||||
|         throw DebugException(message.invoke()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| inline fun debugWarning(message: () -> String) { | ||||
|     if (BuildConfig.DEBUG) { | ||||
|         logError(DebugException(message.invoke())) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| inline fun debugAssert(assert: () -> Boolean, message: () -> String) { | ||||
|     if (BuildConfig.DEBUG && assert.invoke()) { | ||||
|         throw DebugException(message.invoke()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| inline fun debugWarning(assert: () -> Boolean, message: () -> String) { | ||||
|     if (BuildConfig.DEBUG && assert.invoke()) { | ||||
|         logError(DebugException(message.invoke())) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fun <T> LifecycleOwner.observe(liveData: LiveData<T>, action: (t: T) -> Unit) { | ||||
|     liveData.observe(this) { it?.let { t -> action(t) } } | ||||
| } | ||||
|  | @ -61,11 +90,12 @@ suspend fun <T> suspendSafeApiCall(apiCall: suspend () -> T): T? { | |||
| } | ||||
| 
 | ||||
| fun <T> safeFail(throwable: Throwable): Resource<T> { | ||||
|     val stackTraceMsg = (throwable.localizedMessage ?: "") + "\n\n" + throwable.stackTrace.joinToString( | ||||
|         separator = "\n" | ||||
|     ) { | ||||
|         "${it.fileName} ${it.lineNumber}" | ||||
|     } | ||||
|     val stackTraceMsg = | ||||
|         (throwable.localizedMessage ?: "") + "\n\n" + throwable.stackTrace.joinToString( | ||||
|             separator = "\n" | ||||
|         ) { | ||||
|             "${it.fileName} ${it.lineNumber}" | ||||
|         } | ||||
|     return Resource.Failure(false, null, null, stackTraceMsg) | ||||
| } | ||||
| 
 | ||||
|  | @ -92,16 +122,31 @@ suspend fun <T> safeApiCall( | |||
|                     safeFail(throwable) | ||||
|                 } | ||||
|                 is SocketTimeoutException -> { | ||||
|                     Resource.Failure(true, null, null, "Connection Timeout\nPlease try again later.") | ||||
|                     Resource.Failure( | ||||
|                         true, | ||||
|                         null, | ||||
|                         null, | ||||
|                         "Connection Timeout\nPlease try again later." | ||||
|                     ) | ||||
|                 } | ||||
|                 is HttpException -> { | ||||
|                     Resource.Failure(false, throwable.statusCode, null, throwable.message ?: "HttpException") | ||||
|                     Resource.Failure( | ||||
|                         false, | ||||
|                         throwable.statusCode, | ||||
|                         null, | ||||
|                         throwable.message ?: "HttpException" | ||||
|                     ) | ||||
|                 } | ||||
|                 is UnknownHostException -> { | ||||
|                     Resource.Failure(true, null, null, "Cannot connect to server, try again later.") | ||||
|                 } | ||||
|                 is ErrorLoadingException -> { | ||||
|                     Resource.Failure(true, null, null, throwable.message ?: "Error loading, try again later.") | ||||
|                     Resource.Failure( | ||||
|                         true, | ||||
|                         null, | ||||
|                         null, | ||||
|                         throwable.message ?: "Error loading, try again later." | ||||
|                     ) | ||||
|                 } | ||||
|                 is NotImplementedError -> { | ||||
|                     Resource.Failure(false, null, null, "This operation is not implemented.") | ||||
|  |  | |||
|  | @ -29,6 +29,7 @@ class APIRepository(val api: MainAPI) { | |||
|     val hasMainPage = api.hasMainPage | ||||
|     val name = api.name | ||||
|     val mainUrl = api.mainUrl | ||||
|     val mainPage = api.mainPage | ||||
|     val hasQuickSearch = api.hasQuickSearch | ||||
| 
 | ||||
|     suspend fun load(url: String): Resource<LoadResponse> { | ||||
|  | @ -59,9 +60,13 @@ class APIRepository(val api: MainAPI) { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     suspend fun getMainPage(): Resource<HomePageResponse?> { | ||||
|     suspend fun getMainPage(page: Int, nameIndex: Int? = null): Resource<List<HomePageResponse?>> { | ||||
|         return safeApiCall { | ||||
|             api.getMainPage() ?: throw ErrorLoadingException() | ||||
|             nameIndex?.let { api.mainPage.getOrNull(it) }?.let { data -> | ||||
|                 listOf(api.getMainPage(page, data.name, data.data)) | ||||
|             } ?: api.mainPage.apmap { data -> | ||||
|                 api.getMainPage(page, data.name, data.data) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -20,10 +20,8 @@ import androidx.core.widget.NestedScrollView | |||
| import androidx.fragment.app.Fragment | ||||
| import androidx.fragment.app.activityViewModels | ||||
| import androidx.preference.PreferenceManager | ||||
| import androidx.recyclerview.widget.GridLayoutManager | ||||
| import androidx.recyclerview.widget.LinearLayoutManager | ||||
| import androidx.recyclerview.widget.LinearSnapHelper | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import com.google.android.material.bottomsheet.BottomSheetDialog | ||||
| import com.google.android.material.button.MaterialButton | ||||
| import com.lagradost.cloudstream3.* | ||||
|  | @ -44,7 +42,6 @@ import com.lagradost.cloudstream3.ui.WatchType | |||
| import com.lagradost.cloudstream3.ui.quicksearch.QuickSearchFragment | ||||
| import com.lagradost.cloudstream3.ui.result.START_ACTION_RESUME_LATEST | ||||
| import com.lagradost.cloudstream3.ui.search.* | ||||
| import com.lagradost.cloudstream3.ui.search.SearchFragment.Companion.filterSearchResponse | ||||
| import com.lagradost.cloudstream3.ui.search.SearchHelper.handleSearchClickCallback | ||||
| import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings | ||||
| import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings | ||||
|  | @ -349,8 +346,6 @@ class HomeFragment : Fragment() { | |||
|         return inflater.inflate(layout, container, false) | ||||
|     } | ||||
| 
 | ||||
|     private var currentHomePage: HomePageResponse? = null | ||||
| 
 | ||||
|     private fun toggleMainVisibility(visible: Boolean) { | ||||
|         home_main_holder?.isVisible = visible | ||||
|         home_main_poster_recyclerview?.isVisible = visible | ||||
|  | @ -541,18 +536,8 @@ class HomeFragment : Fragment() { | |||
|                     val d = data.value | ||||
|                     listHomepageItems.clear() | ||||
| 
 | ||||
|                     currentHomePage = d | ||||
|                     (home_master_recycler?.adapter as? ParentItemAdapter?)?.updateList( | ||||
|                         d?.items?.mapNotNull { | ||||
|                             try { | ||||
|                                 val filter = it.list.filterSearchResponse() | ||||
|                                 listHomepageItems.addAll(filter) | ||||
|                                 it.copy(list = filter) | ||||
|                             } catch (e: Exception) { | ||||
|                                 logError(e) | ||||
|                                 null | ||||
|                             } | ||||
|                         } ?: listOf()) | ||||
|                     // println("ITEMCOUNT: ${d.values.size} ${home_master_recycler?.adapter?.itemCount}") | ||||
|                     (home_master_recycler?.adapter as? ParentItemAdapter?)?.updateList(d.values.toMutableList()) | ||||
| 
 | ||||
|                     home_loading?.isVisible = false | ||||
|                     home_loading_error?.isVisible = false | ||||
|  | @ -603,13 +588,6 @@ class HomeFragment : Fragment() { | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> = | ||||
|             ParentItemAdapter(mutableListOf(), { callback -> | ||||
|                 homeHandleSearch(callback) | ||||
|             }, { item -> | ||||
|                 activity?.loadHomepageList(item) | ||||
|             }) | ||||
| 
 | ||||
|         val toggleList = listOf( | ||||
|             Pair(home_type_watching_btt, WatchType.WATCHING), | ||||
|             Pair(home_type_completed_btt, WatchType.COMPLETED), | ||||
|  | @ -861,9 +839,19 @@ class HomeFragment : Fragment() { | |||
|         context?.fixPaddingStatusbarView(home_statusbar) | ||||
|         context?.fixPaddingStatusbar(home_loading_statusbar) | ||||
| 
 | ||||
| 
 | ||||
|         home_master_recycler.adapter = adapter | ||||
|         home_master_recycler.layoutManager = GridLayoutManager(context, 1) | ||||
|         home_master_recycler.adapter = | ||||
|             ParentItemAdapter(mutableListOf(), { callback -> | ||||
|                 homeHandleSearch(callback) | ||||
|             }, { item -> | ||||
|                 activity?.loadHomepageList(item) | ||||
|             }, { name -> | ||||
|                 homeViewModel.expand(name) | ||||
|             }) | ||||
|         home_master_recycler.layoutManager = object : LinearLayoutManager(context) { | ||||
|             override fun supportsPredictiveItemAnimations(): Boolean { | ||||
|                 return false | ||||
|             } | ||||
|         }; // GridLayoutManager(context, 1).also { it.supportsPredictiveItemAnimations() } | ||||
| 
 | ||||
|         if (context?.isTvSettings() == false) { | ||||
|             LinearSnapHelper().attachToRecyclerView(home_main_poster_recyclerview) // snap | ||||
|  |  | |||
|  | @ -13,18 +13,22 @@ import com.lagradost.cloudstream3.ui.search.SearchClickCallback | |||
| import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings | ||||
| import kotlinx.android.synthetic.main.homepage_parent.view.* | ||||
| 
 | ||||
| 
 | ||||
| class ParentItemAdapter( | ||||
|     private var items: MutableList<HomePageList>, | ||||
|     private var items: MutableList<HomeViewModel.ExpandableHomepageList>, | ||||
|     private val clickCallback: (SearchClickCallback) -> Unit, | ||||
|     private val moreInfoClickCallback: (HomePageList) -> Unit, | ||||
|     private val expandCallback: ((String) -> Unit)? = null, | ||||
| ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { | ||||
| 
 | ||||
|     override fun onCreateViewHolder(parent: ViewGroup, i: Int): ParentViewHolder { | ||||
|         val layout = | ||||
|             if (parent.context.isTvSettings()) R.layout.homepage_parent_tv else R.layout.homepage_parent | ||||
|         return ParentViewHolder( | ||||
|             LayoutInflater.from(parent.context).inflate(layout, parent, false), | ||||
|             clickCallback, | ||||
|             moreInfoClickCallback | ||||
|             moreInfoClickCallback, | ||||
|             expandCallback | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|  | @ -41,28 +45,41 @@ class ParentItemAdapter( | |||
|     } | ||||
| 
 | ||||
|     override fun getItemId(position: Int): Long { | ||||
|         return items[position].name.hashCode().toLong() | ||||
|         return items[position].list.name.hashCode().toLong() | ||||
|     } | ||||
| 
 | ||||
|     @JvmName("updateListHomePageList") | ||||
|     fun updateList(newList: List<HomePageList>) { | ||||
|         // this moves all bad results to the bottom | ||||
|         val endList = mutableListOf<HomePageList>() | ||||
|         val newFilteredList = mutableListOf<HomePageList>() | ||||
|         for (item in newList) { | ||||
|             if (item.list.isEmpty()) { | ||||
|                 endList.add(item) | ||||
|             } else { | ||||
|                 newFilteredList.add(item) | ||||
|             } | ||||
|         } | ||||
|         newFilteredList.addAll(endList) | ||||
|         updateList(newList.map { HomeViewModel.ExpandableHomepageList(it, 1, false) } | ||||
|             .toMutableList()) | ||||
|     } | ||||
| 
 | ||||
|     @JvmName("updateListExpandableHomepageList") | ||||
|     fun updateList(newList: MutableList<HomeViewModel.ExpandableHomepageList>) { | ||||
|         val diffResult = DiffUtil.calculateDiff( | ||||
|             SearchDiffCallback(this.items, newFilteredList) | ||||
|             SearchDiffCallback(items, newList) | ||||
|         ) | ||||
| 
 | ||||
|         items.clear() | ||||
|         items.addAll(newFilteredList) | ||||
|         items.addAll(newList.map { it.copy(list = it.list.copy()) }) // I have to do this otherwise it is a "copy" and dispatchUpdatesTo wont work | ||||
| 
 | ||||
|         /*val mAdapter = this | ||||
|         diffResult.dispatchUpdatesTo(object : ListUpdateCallback { | ||||
|             override fun onInserted(position: Int, count: Int) { | ||||
|                 mAdapter.notifyItemRangeInserted(position, count) | ||||
|             } | ||||
| 
 | ||||
|             override fun onRemoved(position: Int, count: Int) { | ||||
|                 mAdapter.notifyItemRangeRemoved(position, count) | ||||
|             } | ||||
| 
 | ||||
|             override fun onMoved(fromPosition: Int, toPosition: Int) { | ||||
|                 mAdapter.notifyItemMoved(fromPosition, toPosition) | ||||
|             } | ||||
| 
 | ||||
|             override fun onChanged(position: Int, count: Int, payload: Any?) { | ||||
|                 mAdapter.notifyItemRangeChanged(position, count, payload) | ||||
|             } | ||||
|         })*/ | ||||
| 
 | ||||
|         diffResult.dispatchUpdatesTo(this) | ||||
|     } | ||||
|  | @ -71,14 +88,16 @@ class ParentItemAdapter( | |||
|     constructor( | ||||
|         itemView: View, | ||||
|         private val clickCallback: (SearchClickCallback) -> Unit, | ||||
|         private val moreInfoClickCallback: (HomePageList) -> Unit | ||||
|         private val moreInfoClickCallback: (HomePageList) -> Unit, | ||||
|         private val expandCallback: ((String) -> Unit)? = null, | ||||
|     ) : | ||||
|         RecyclerView.ViewHolder(itemView) { | ||||
|         val title: TextView = itemView.home_parent_item_title | ||||
|         val recyclerView: RecyclerView = itemView.home_child_recyclerview | ||||
|         private val moreInfo: FrameLayout? = itemView.home_child_more_info | ||||
|         fun bind(info: HomePageList) { | ||||
|             title.text = info.name | ||||
| 
 | ||||
|         fun bind(expand: HomeViewModel.ExpandableHomepageList) { | ||||
|             val info = expand.list | ||||
|             recyclerView.adapter = HomeChildItemAdapter( | ||||
|                 info.list.toMutableList(), | ||||
|                 clickCallback = clickCallback, | ||||
|  | @ -88,6 +107,23 @@ class ParentItemAdapter( | |||
|                 isHorizontal = info.isHorizontalImages | ||||
|             } | ||||
| 
 | ||||
|             title.text = info.name | ||||
| 
 | ||||
|             recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() { | ||||
|                 var expandCount = 0 | ||||
|                 val name = expand.list.name | ||||
| 
 | ||||
|                 override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { | ||||
|                     super.onScrollStateChanged(recyclerView, newState) | ||||
| 
 | ||||
|                     val count = recyclerView.adapter?.itemCount ?: return | ||||
|                     if (!recyclerView.canScrollHorizontally(1) && expand.hasNext && expandCount != count) { | ||||
|                         expandCount = count | ||||
|                         expandCallback?.invoke(name) | ||||
|                     } | ||||
|                 } | ||||
|             }) | ||||
| 
 | ||||
|             //(recyclerView.adapter as HomeChildItemAdapter).notifyDataSetChanged() | ||||
| 
 | ||||
|             moreInfo?.setOnClickListener { | ||||
|  | @ -98,17 +134,22 @@ class ParentItemAdapter( | |||
| } | ||||
| 
 | ||||
| class SearchDiffCallback( | ||||
|     private val oldList: List<HomePageList>, | ||||
|     private val newList: List<HomePageList> | ||||
|     private val oldList: List<HomeViewModel.ExpandableHomepageList>, | ||||
|     private val newList: List<HomeViewModel.ExpandableHomepageList> | ||||
| ) : | ||||
|     DiffUtil.Callback() { | ||||
|     override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) = | ||||
|         oldList[oldItemPosition].name == newList[newItemPosition].name | ||||
|         oldList[oldItemPosition].list.name == newList[newItemPosition].list.name | ||||
| 
 | ||||
|     override fun getOldListSize() = oldList.size | ||||
| 
 | ||||
|     override fun getNewListSize() = newList.size | ||||
| 
 | ||||
|     override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) = | ||||
|     override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean = | ||||
|         oldList[oldItemPosition] == newList[newItemPosition] | ||||
|     //{ | ||||
|     //    val ret = oldList[oldItemPosition].list.list.size == newList[newItemPosition].list.list.size | ||||
|     //    println(">>>>>>>>>>>>>>>> $ret ${oldList[oldItemPosition].list.list.size} == ${newList[newItemPosition].list.list.size}") | ||||
|     //    return ret | ||||
|     //} | ||||
| } | ||||
|  | @ -10,10 +10,12 @@ import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull | |||
| import com.lagradost.cloudstream3.AcraApplication.Companion.context | ||||
| import com.lagradost.cloudstream3.AcraApplication.Companion.getKey | ||||
| import com.lagradost.cloudstream3.AcraApplication.Companion.setKey | ||||
| import com.lagradost.cloudstream3.HomePageResponse | ||||
| import com.lagradost.cloudstream3.HomePageList | ||||
| import com.lagradost.cloudstream3.MainAPI | ||||
| import com.lagradost.cloudstream3.SearchResponse | ||||
| import com.lagradost.cloudstream3.mvvm.Resource | ||||
| import com.lagradost.cloudstream3.mvvm.debugAssert | ||||
| import com.lagradost.cloudstream3.mvvm.debugWarning | ||||
| import com.lagradost.cloudstream3.mvvm.logError | ||||
| import com.lagradost.cloudstream3.ui.APIRepository | ||||
| import com.lagradost.cloudstream3.ui.APIRepository.Companion.noneApi | ||||
|  | @ -34,6 +36,7 @@ import kotlinx.coroutines.Job | |||
| import kotlinx.coroutines.launch | ||||
| import kotlinx.coroutines.withContext | ||||
| import java.util.* | ||||
| import kotlin.collections.set | ||||
| 
 | ||||
| class HomeViewModel : ViewModel() { | ||||
|     private var repo: APIRepository? = null | ||||
|  | @ -41,9 +44,6 @@ class HomeViewModel : ViewModel() { | |||
|     private val _apiName = MutableLiveData<String>() | ||||
|     val apiName: LiveData<String> = _apiName | ||||
| 
 | ||||
|     private val _page = MutableLiveData<Resource<HomePageResponse?>>() | ||||
|     val page: LiveData<Resource<HomePageResponse?>> = _page | ||||
| 
 | ||||
|     private val _randomItems = MutableLiveData<List<SearchResponse>?>(null) | ||||
|     val randomItems: LiveData<List<SearchResponse>?> = _randomItems | ||||
| 
 | ||||
|  | @ -51,8 +51,10 @@ class HomeViewModel : ViewModel() { | |||
|         return APIRepository(apis.first { it.hasMainPage }) | ||||
|     } | ||||
| 
 | ||||
|     private val _availableWatchStatusTypes = MutableLiveData<Pair<EnumSet<WatchType>, EnumSet<WatchType>>>() | ||||
|     val availableWatchStatusTypes: LiveData<Pair<EnumSet<WatchType>, EnumSet<WatchType>>> = _availableWatchStatusTypes | ||||
|     private val _availableWatchStatusTypes = | ||||
|         MutableLiveData<Pair<EnumSet<WatchType>, EnumSet<WatchType>>>() | ||||
|     val availableWatchStatusTypes: LiveData<Pair<EnumSet<WatchType>, EnumSet<WatchType>>> = | ||||
|         _availableWatchStatusTypes | ||||
|     private val _bookmarks = MutableLiveData<Pair<Boolean, List<SearchResponse>>>() | ||||
|     val bookmarks: LiveData<Pair<Boolean, List<SearchResponse>>> = _bookmarks | ||||
| 
 | ||||
|  | @ -143,6 +145,64 @@ class HomeViewModel : ViewModel() { | |||
|         onGoingLoad = load(api) | ||||
|     } | ||||
| 
 | ||||
|     data class ExpandableHomepageList( | ||||
|         var list: HomePageList, | ||||
|         var currentPage: Int, | ||||
|         var hasNext: Boolean, | ||||
|     ) | ||||
| 
 | ||||
|     private val expandable: MutableMap<String, ExpandableHomepageList> = mutableMapOf() | ||||
|     private val _page = | ||||
|         MutableLiveData<Resource<Map<String, ExpandableHomepageList>>>(Resource.Loading()) | ||||
|     val page: LiveData<Resource<Map<String, ExpandableHomepageList>>> = _page | ||||
| 
 | ||||
|     val lock: MutableSet<String> = mutableSetOf() | ||||
| 
 | ||||
|     // this is soo over engineered, but idk how I can make it clean without making the main api harder to use :pensive: | ||||
|     fun expand(name: String) = viewModelScope.launch { | ||||
|         if (lock.contains(name)) return@launch | ||||
|         lock += name | ||||
| 
 | ||||
|         repo?.apply { | ||||
|             expandable[name]?.let { current -> | ||||
|                 debugAssert({ !current.hasNext }) { | ||||
|                     "Expand called when not needed" | ||||
|                 } | ||||
| 
 | ||||
|                 val nextPage = current.currentPage + 1 | ||||
|                 val next = getMainPage(nextPage, mainPage.indexOfFirst { it.name == name }) | ||||
|                 if (next is Resource.Success) { | ||||
|                     next.value.filterNotNull().forEach { main -> | ||||
|                         main.items.forEach { newList -> | ||||
|                             val key = newList.name | ||||
|                             expandable[key]?.apply { | ||||
|                                 hasNext = main.hasNext | ||||
|                                 currentPage = nextPage | ||||
| 
 | ||||
|                                 debugWarning({ newList.list.any { outer -> this.list.list.any { it.url == outer.url } } }) { | ||||
|                                     "Expanded contained an item that was previously already in the list\n${list.name} = ${this.list.list}\n${newList.name} = ${newList.list}" | ||||
|                                 } | ||||
| 
 | ||||
|                                 val before = list.list.size | ||||
|                                 this.list.list += newList.list | ||||
|                                 this.list.list.distinctBy { it.url } // just to be sure we are not adding the same shit for some reason | ||||
|                                 expandable[key] = this | ||||
|                                 val after = list.list.size | ||||
|                             } ?: debugWarning { | ||||
|                                 "Expanded an item not in main load named $key, current list is ${expandable.keys}" | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } else { | ||||
|                     current.hasNext = false | ||||
|                 } | ||||
|             } | ||||
|             _page.postValue(Resource.Success(expandable)) | ||||
|         } | ||||
| 
 | ||||
|         lock -= name | ||||
|     } | ||||
| 
 | ||||
|     private fun load(api: MainAPI?) = viewModelScope.launch { | ||||
|         repo = if (api != null) { | ||||
|             APIRepository(api) | ||||
|  | @ -156,35 +216,43 @@ class HomeViewModel : ViewModel() { | |||
|         if (repo?.hasMainPage == true) { | ||||
|             _page.postValue(Resource.Loading()) | ||||
| 
 | ||||
|             val data = repo?.getMainPage() | ||||
|             when (data) { | ||||
|             when (val data = repo?.getMainPage(1, null)) { | ||||
|                 is Resource.Success -> { | ||||
|                     try { | ||||
|                         val home = data.value | ||||
|                         if (home?.items?.isNullOrEmpty() == false) { | ||||
|                         expandable.clear() | ||||
|                         data.value.forEach { home -> | ||||
|                             home?.items?.forEach { list -> | ||||
|                                 expandable[list.name] = | ||||
|                                     ExpandableHomepageList(list, 1, home.hasNext) | ||||
|                             } | ||||
|                         } | ||||
|                         _page.postValue(Resource.Success(expandable)) | ||||
|                         val items = data.value.mapNotNull { it?.items }.flatten() | ||||
| 
 | ||||
|                         //val home = data.value | ||||
|                         if (items.isNotEmpty()) { | ||||
|                             val currentList = | ||||
|                                 home.items.shuffled().filter { !it.list.isNullOrEmpty() }.flatMap { it.list } | ||||
|                                 items.shuffled().filter { it.list.isNotEmpty() } | ||||
|                                     .flatMap { it.list } | ||||
|                                     .distinctBy { it.url } | ||||
|                                     .toList() | ||||
| 
 | ||||
|                             if (!currentList.isNullOrEmpty()) { | ||||
|                             if (currentList.isNotEmpty()) { | ||||
|                                 val randomItems = currentList.shuffled() | ||||
| 
 | ||||
|                                 _randomItems.postValue(randomItems) | ||||
|                             } | ||||
|                         } | ||||
|                     } catch (e : Exception) { | ||||
|                     } catch (e: Exception) { | ||||
|                         _randomItems.postValue(emptyList()) | ||||
|                         logError(e) | ||||
|                     } | ||||
|                 } | ||||
|                 is Resource.Failure -> { | ||||
|                     _page.postValue(data!!) | ||||
|                 } | ||||
|                 else -> Unit | ||||
|             } | ||||
|             data?.let { | ||||
|                 _page.postValue(it) | ||||
|             } | ||||
|         } else { | ||||
|             _page.postValue(Resource.Success(HomePageResponse(emptyList()))) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -194,7 +262,7 @@ class HomeViewModel : ViewModel() { | |||
|             loadAndCancel(noneApi) | ||||
|         else if (preferredApiName == randomApi.name || api == null) { | ||||
|             val validAPIs = context?.filterProviderByPreferredMedia() | ||||
|             if(validAPIs.isNullOrEmpty()) { | ||||
|             if (validAPIs.isNullOrEmpty()) { | ||||
|                 loadAndCancel(noneApi) | ||||
|             } else { | ||||
|                 val apiRandom = validAPIs.random() | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue