forked from recloudstream/cloudstream
		
	moved to List + animations
This commit is contained in:
		
							parent
							
								
									5d20feb2ad
								
							
						
					
					
						commit
						8aa907d1d9
					
				
					 13 changed files with 296 additions and 267 deletions
				
			
		|  | @ -6,10 +6,17 @@ import android.content.res.ColorStateList | |||
| import android.content.res.Configuration | ||||
| import android.os.Bundle | ||||
| import android.view.KeyEvent | ||||
| import android.view.Menu | ||||
| import android.view.MenuItem | ||||
| import android.view.WindowManager | ||||
| import androidx.annotation.IdRes | ||||
| import androidx.appcompat.app.AppCompatActivity | ||||
| import androidx.core.view.isVisible | ||||
| import androidx.navigation.NavController | ||||
| import androidx.navigation.NavDestination | ||||
| import androidx.navigation.NavDestination.Companion.hierarchy | ||||
| import androidx.navigation.NavGraph.Companion.findStartDestination | ||||
| import androidx.navigation.NavOptions | ||||
| import androidx.navigation.findNavController | ||||
| import androidx.navigation.ui.setupWithNavController | ||||
| import androidx.preference.PreferenceManager | ||||
|  | @ -270,6 +277,31 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private fun NavDestination.matchDestination(@IdRes destId: Int): Boolean = | ||||
|         hierarchy.any { it.id == destId } | ||||
| 
 | ||||
|     private fun onNavDestinationSelected(item: MenuItem, navController: NavController): Boolean { | ||||
|         val builder = NavOptions.Builder().setLaunchSingleTop(true).setRestoreState(true) | ||||
|             .setEnterAnim(R.anim.enter_anim) | ||||
|             .setExitAnim(R.anim.exit_anim) | ||||
|             .setPopEnterAnim(R.anim.pop_enter) | ||||
|             .setPopExitAnim(R.anim.pop_exit) | ||||
|         if (item.order and Menu.CATEGORY_SECONDARY == 0) { | ||||
|             builder.setPopUpTo( | ||||
|                 navController.graph.findStartDestination().id, | ||||
|                 inclusive = false, | ||||
|                 saveState = true | ||||
|             ) | ||||
|         } | ||||
|         val options = builder.build() | ||||
|         return try { | ||||
|             navController.navigate(item.itemId, null, options) | ||||
|             navController.currentDestination?.matchDestination(item.itemId) == true | ||||
|         } catch (e: IllegalArgumentException) { | ||||
|             false | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun onCreate(savedInstanceState: Bundle?) { | ||||
|         // init accounts | ||||
|         for (api in OAuth2accountApis) { | ||||
|  | @ -315,9 +347,23 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { | |||
|         nav_view?.setupWithNavController(navController) | ||||
|         val navRail = findViewById<NavigationRailView?>(R.id.nav_rail_view) | ||||
|         navRail?.setupWithNavController(navController) | ||||
| 
 | ||||
|         navRail?.setOnItemSelectedListener { item -> | ||||
|             onNavDestinationSelected( | ||||
|                 item, | ||||
|                 navController | ||||
|             ) | ||||
|         } | ||||
|         nav_view?.setOnItemSelectedListener { item -> | ||||
|             onNavDestinationSelected( | ||||
|                 item, | ||||
|                 navController | ||||
|             ) | ||||
|         } | ||||
|         navController.addOnDestinationChangedListener { _, destination, _ -> | ||||
|             updateNavBar(destination) | ||||
|         } | ||||
| 
 | ||||
|         loadCache() | ||||
| 
 | ||||
|         /*nav_view.setOnNavigationItemSelectedListener { item -> | ||||
|  |  | |||
|  | @ -140,14 +140,14 @@ class AnimePaheProvider : MainAPI() { | |||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     override suspend fun search(query: String): ArrayList<SearchResponse> { | ||||
|     override suspend fun search(query: String): List<SearchResponse> { | ||||
|         val url = "$mainUrl/api?m=search&l=8&q=$query" | ||||
|         val headers = mapOf("referer" to "$mainUrl/") | ||||
| 
 | ||||
|         val req = app.get(url, headers = headers).text | ||||
|         val data = req.let { mapper.readValue<AnimePaheSearch>(it) } | ||||
| 
 | ||||
|         return ArrayList(data.data.map { | ||||
|         return data.data.map { | ||||
|             AnimeSearchResponse( | ||||
|                 it.title, | ||||
|                 "https://pahe.win/a/${it.id}?slug=${it.title}", | ||||
|  | @ -160,7 +160,7 @@ class AnimePaheProvider : MainAPI() { | |||
|                 null, | ||||
|                 it.episodes | ||||
|             ) | ||||
|         }) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private data class AnimeData( | ||||
|  |  | |||
|  | @ -4,7 +4,6 @@ import com.lagradost.cloudstream3.* | |||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.loadExtractor | ||||
| import java.util.* | ||||
| import kotlin.collections.ArrayList | ||||
| 
 | ||||
| class AnimeflvnetProvider : MainAPI() { | ||||
|     companion object { | ||||
|  | @ -63,11 +62,10 @@ class AnimeflvnetProvider : MainAPI() { | |||
|         return HomePageResponse(items) | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun search(query: String): ArrayList<SearchResponse> { | ||||
| 
 | ||||
|     override suspend fun search(query: String): List<SearchResponse> { | ||||
|         val url = "${mainUrl}/browse?q=${query}" | ||||
|         val doc = app.get(url).document | ||||
|         val episodes = doc.select("ul.List-Animes li.Anime").map { | ||||
|         return doc.select("ul.List-Animes li.Anime").map { | ||||
|             val title = it.selectFirst("h2.title").text() | ||||
|             val href = fixUrl(it.selectFirst("a").attr("href")) | ||||
|             val image = it.selectFirst(".Image img").attr("src") | ||||
|  | @ -83,7 +81,6 @@ class AnimeflvnetProvider : MainAPI() { | |||
|                 ), | ||||
|             ) | ||||
|         } | ||||
|         return ArrayList(episodes) | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun load(url: String): LoadResponse { | ||||
|  |  | |||
|  | @ -73,7 +73,10 @@ class DubbedAnimeProvider : MainAPI() { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private suspend fun parseDocument(url: String, trimEpisode: Boolean = false): List<SearchResponse> { | ||||
|     private suspend fun parseDocument( | ||||
|         url: String, | ||||
|         trimEpisode: Boolean = false | ||||
|     ): List<SearchResponse> { | ||||
|         val response = app.get(url).text | ||||
|         val document = Jsoup.parse(response) | ||||
|         return document.select("a.grid__link").map { | ||||
|  | @ -131,31 +134,28 @@ class DubbedAnimeProvider : MainAPI() { | |||
|         val response = app.get(url).text | ||||
|         val document = Jsoup.parse(response) | ||||
|         val items = document.select("div.grid__item > a") | ||||
|         if (items.isEmpty()) return ArrayList() | ||||
|         val returnValue = ArrayList<SearchResponse>() | ||||
|         for (i in items) { | ||||
|         if (items.isEmpty()) return emptyList() | ||||
|         return items.map { i -> | ||||
|             val href = fixUrl(i.attr("href")) | ||||
|             val title = i.selectFirst("div.gridtitlek").text() | ||||
|             val img = fixUrlNull(i.selectFirst("img.grid__img")?.attr("src")) | ||||
|             returnValue.add( | ||||
|                 if (getIsMovie(href)) { | ||||
|                     MovieSearchResponse( | ||||
|                         title, href, this.name, TvType.AnimeMovie, img, null | ||||
|                     ) | ||||
|                 } else { | ||||
|                     AnimeSearchResponse( | ||||
|                         title, | ||||
|                         href, | ||||
|                         this.name, | ||||
|                         TvType.Anime, | ||||
|                         img, | ||||
|                         null, | ||||
|                         EnumSet.of(DubStatus.Dubbed), | ||||
|                     ) | ||||
|                 } | ||||
|             ) | ||||
| 
 | ||||
|             if (getIsMovie(href)) { | ||||
|                 MovieSearchResponse( | ||||
|                     title, href, this.name, TvType.AnimeMovie, img, null | ||||
|                 ) | ||||
|             } else { | ||||
|                 AnimeSearchResponse( | ||||
|                     title, | ||||
|                     href, | ||||
|                     this.name, | ||||
|                     TvType.Anime, | ||||
|                     img, | ||||
|                     null, | ||||
|                     EnumSet.of(DubStatus.Dubbed), | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
|         return returnValue | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun search(query: String): List<SearchResponse> { | ||||
|  | @ -164,33 +164,28 @@ class DubbedAnimeProvider : MainAPI() { | |||
|         val document = Jsoup.parse(response) | ||||
|         val items = document.select("div.resultinner > a.resulta") | ||||
|         if (items.isEmpty()) return ArrayList() | ||||
|         val returnValue = ArrayList<SearchResponse>() | ||||
|         for (i in items) { | ||||
|         return items.map { i -> | ||||
|             val innerDiv = i.selectFirst("> div.result") | ||||
|             val href = fixUrl(i.attr("href")) | ||||
|             val img = fixUrl(innerDiv.selectFirst("> div.imgkz > img").attr("src")) | ||||
|             val title = innerDiv.selectFirst("> div.titleresults").text() | ||||
| 
 | ||||
|             returnValue.add( | ||||
|                 if (getIsMovie(href)) { | ||||
|                     MovieSearchResponse( | ||||
|                         title, href, this.name, TvType.AnimeMovie, img, null | ||||
|                     ) | ||||
|                 } else { | ||||
|                     AnimeSearchResponse( | ||||
|                         title, | ||||
|                         href, | ||||
|                         this.name, | ||||
|                         TvType.Anime, | ||||
|                         img, | ||||
|                         null, | ||||
|                         EnumSet.of(DubStatus.Dubbed), | ||||
|                     ) | ||||
|                 } | ||||
|             ) | ||||
|             if (getIsMovie(href)) { | ||||
|                 MovieSearchResponse( | ||||
|                     title, href, this.name, TvType.AnimeMovie, img, null | ||||
|                 ) | ||||
|             } else { | ||||
|                 AnimeSearchResponse( | ||||
|                     title, | ||||
|                     href, | ||||
|                     this.name, | ||||
|                     TvType.Anime, | ||||
|                     img, | ||||
|                     null, | ||||
|                     EnumSet.of(DubStatus.Dubbed), | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return returnValue | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun loadLinks( | ||||
|  |  | |||
|  | @ -191,7 +191,7 @@ class TenshiProvider : MainAPI() { | |||
| //        return returnValue | ||||
| //    } | ||||
| 
 | ||||
|     override suspend fun search(query: String): ArrayList<SearchResponse> { | ||||
|     override suspend fun search(query: String): List<SearchResponse> { | ||||
|         val url = "$mainUrl/anime" | ||||
|         var document = app.get( | ||||
|             url, | ||||
|  | @ -203,10 +203,10 @@ class TenshiProvider : MainAPI() { | |||
|         val returnValue = parseSearchPage(document).toMutableList() | ||||
| 
 | ||||
|         while (!document.select("""a.page-link[rel="next"]""").isEmpty()) { | ||||
|             val link = document.select("""a.page-link[rel="next"]""") | ||||
|             if (link != null && !link.isEmpty()) { | ||||
|             val link = document.selectFirst("""a.page-link[rel="next"]""")?.attr("href") | ||||
|             if (!link.isNullOrBlank()) { | ||||
|                 document = app.get( | ||||
|                     link[0].attr("href"), | ||||
|                     link, | ||||
|                     cookies = mapOf("loop-view" to "thumb"), | ||||
|                     interceptor = ddosGuardKiller | ||||
|                 ).document | ||||
|  | @ -216,7 +216,7 @@ class TenshiProvider : MainAPI() { | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return ArrayList(returnValue) | ||||
|         return returnValue | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun load(url: String): LoadResponse { | ||||
|  |  | |||
|  | @ -79,11 +79,10 @@ class WcoProvider : MainAPI() { | |||
|         return "$mainUrl/anime/$aniId" | ||||
|     } | ||||
| 
 | ||||
|     private fun parseSearchPage(soup: Document): ArrayList<SearchResponse> { | ||||
|     private fun parseSearchPage(soup: Document): List<SearchResponse> { | ||||
|         val items = soup.select(".film_list-wrap > .flw-item") | ||||
|         if (items.isEmpty()) return ArrayList() | ||||
|         val returnValue = ArrayList<SearchResponse>() | ||||
|         for (i in items) { | ||||
|         return items.map { i -> | ||||
|             val href = fixAnimeLink(i.selectFirst("a").attr("href")) | ||||
|             val img = fixUrl(i.selectFirst("img").attr("data-src")) | ||||
|             val title = i.selectFirst("img").attr("title") | ||||
|  | @ -94,25 +93,22 @@ class WcoProvider : MainAPI() { | |||
|             val type = | ||||
|                 i.selectFirst(".film-detail.film-detail-fix > div > span:nth-child(3)").text() | ||||
| 
 | ||||
|             returnValue.add( | ||||
|                 if (getType(type) == TvType.AnimeMovie) { | ||||
|                     MovieSearchResponse( | ||||
|                         title, href, this.name, TvType.AnimeMovie, img, year | ||||
|                     ) | ||||
|                 } else { | ||||
|                     AnimeSearchResponse( | ||||
|                         title, | ||||
|                         href, | ||||
|                         this.name, | ||||
|                         TvType.Anime, | ||||
|                         img, | ||||
|                         year, | ||||
|                         EnumSet.of(if (isDub) DubStatus.Dubbed else DubStatus.Subbed), | ||||
|                     ) | ||||
|                 } | ||||
|             ) | ||||
|             if (getType(type) == TvType.AnimeMovie) { | ||||
|                 MovieSearchResponse( | ||||
|                     title, href, this.name, TvType.AnimeMovie, img, year | ||||
|                 ) | ||||
|             } else { | ||||
|                 AnimeSearchResponse( | ||||
|                     title, | ||||
|                     href, | ||||
|                     this.name, | ||||
|                     TvType.Anime, | ||||
|                     img, | ||||
|                     year, | ||||
|                     EnumSet.of(if (isDub) DubStatus.Dubbed else DubStatus.Subbed), | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
|         return returnValue | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun search(query: String): List<SearchResponse> { | ||||
|  | @ -120,7 +116,7 @@ class WcoProvider : MainAPI() { | |||
|         val response = | ||||
|             app.get(url, params = mapOf("keyword" to query)) | ||||
|         var document = Jsoup.parse(response.text) | ||||
|         val returnValue = parseSearchPage(document) | ||||
|         val returnValue = parseSearchPage(document).toMutableList() | ||||
| 
 | ||||
|         while (!document.select(".pagination").isEmpty()) { | ||||
|             val link = document.select("a.page-link[rel=\"next\"]") | ||||
|  | @ -136,8 +132,6 @@ class WcoProvider : MainAPI() { | |||
|     } | ||||
| 
 | ||||
|     override suspend fun quickSearch(query: String): List<SearchResponse> { | ||||
|         val returnValue: ArrayList<SearchResponse> = ArrayList() | ||||
| 
 | ||||
|         val response = JSONObject( | ||||
|             app.post( | ||||
|                 "https://wcostream.cc/ajax/search", | ||||
|  | @ -146,35 +140,30 @@ class WcoProvider : MainAPI() { | |||
|         ).getString("html") // I won't make a dataclass for this shit | ||||
|         val document = Jsoup.parse(response) | ||||
| 
 | ||||
|         document.select("a.nav-item").forEach { | ||||
|             val title = it.selectFirst("img")?.attr("title").toString() | ||||
|             val img = it?.selectFirst("img")?.attr("src") | ||||
|             val href = it?.attr("href").toString() | ||||
|         return document.select("a.nav-item").mapNotNull { | ||||
|             val title = it.selectFirst("img")?.attr("title") ?: return@mapNotNull null | ||||
|             val img = it?.selectFirst("img")?.attr("src") ?: return@mapNotNull null | ||||
|             val href = it?.attr("href") ?: return@mapNotNull null | ||||
|             val isDub = title.contains("(Dub)") | ||||
|             val filmInfo = it?.selectFirst(".film-infor") | ||||
|             val filmInfo = it.selectFirst(".film-infor") | ||||
|             val year = filmInfo?.select("span")?.get(0)?.text()?.toIntOrNull() | ||||
|             val type = filmInfo?.select("span")?.get(1)?.text().toString() | ||||
|             if (title != "null") { | ||||
|                 returnValue.add( | ||||
|                     if (getType(type) == TvType.AnimeMovie) { | ||||
|                         MovieSearchResponse( | ||||
|                             title, href, this.name, TvType.AnimeMovie, img, year | ||||
|                         ) | ||||
|                     } else { | ||||
|                         AnimeSearchResponse( | ||||
|                             title, | ||||
|                             href, | ||||
|                             this.name, | ||||
|                             TvType.Anime, | ||||
|                             img, | ||||
|                             year, | ||||
|                             EnumSet.of(if (isDub) DubStatus.Dubbed else DubStatus.Subbed), | ||||
|                         ) | ||||
|                     } | ||||
|             if (getType(type) == TvType.AnimeMovie) { | ||||
|                 MovieSearchResponse( | ||||
|                     title, href, this.name, TvType.AnimeMovie, img, year | ||||
|                 ) | ||||
|             } else { | ||||
|                 AnimeSearchResponse( | ||||
|                     title, | ||||
|                     href, | ||||
|                     this.name, | ||||
|                     TvType.Anime, | ||||
|                     img, | ||||
|                     year, | ||||
|                     EnumSet.of(if (isDub) DubStatus.Dubbed else DubStatus.Subbed), | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
|         return returnValue | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun load(url: String): LoadResponse { | ||||
|  |  | |||
|  | @ -37,29 +37,25 @@ class AllMoviesForYouProvider : MainAPI() { | |||
|         val document = app.get(url).document | ||||
| 
 | ||||
|         val items = document.select("ul.MovieList > li > article > a") | ||||
|         val returnValue = ArrayList<SearchResponse>() | ||||
|         for (item in items) { | ||||
|         return items.map { item -> | ||||
|             val href = item.attr("href") | ||||
|             val title = item.selectFirst("> h2.Title").text() | ||||
|             val img = fixUrl(item.selectFirst("> div.Image > figure > img").attr("data-src")) | ||||
|             val type = getType(href) | ||||
|             if (type == TvType.Movie) { | ||||
|                 returnValue.add(MovieSearchResponse(title, href, this.name, type, img, null)) | ||||
|             } else if (type == TvType.TvSeries) { | ||||
|                 returnValue.add( | ||||
|                     TvSeriesSearchResponse( | ||||
|                         title, | ||||
|                         href, | ||||
|                         this.name, | ||||
|                         type, | ||||
|                         img, | ||||
|                         null, | ||||
|                         null | ||||
|                     ) | ||||
|                 MovieSearchResponse(title, href, this.name, type, img, null) | ||||
|             } else { | ||||
|                 TvSeriesSearchResponse( | ||||
|                     title, | ||||
|                     href, | ||||
|                     this.name, | ||||
|                     type, | ||||
|                     img, | ||||
|                     null, | ||||
|                     null | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
|         return returnValue | ||||
|     } | ||||
| 
 | ||||
|     private fun getLink(document: Document): List<String>? { | ||||
|  |  | |||
|  | @ -5,7 +5,6 @@ import com.lagradost.cloudstream3.extractors.FEmbed | |||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.loadExtractor | ||||
| import java.util.* | ||||
| import kotlin.collections.ArrayList | ||||
| 
 | ||||
| 
 | ||||
| class DoramasYTProvider : MainAPI() { | ||||
|  | @ -99,25 +98,23 @@ class DoramasYTProvider : MainAPI() { | |||
|         return HomePageResponse(items) | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun search(query: String): ArrayList<SearchResponse> { | ||||
|         val search = | ||||
|             app.get("$mainUrl/buscar?q=$query", timeout = 120).document.select(".col-6").map { | ||||
|                 val title = it.selectFirst(".animedtls p").text() | ||||
|                 val href = it.selectFirst("a").attr("href") | ||||
|                 val image = it.selectFirst(".animes img").attr("src") | ||||
|                 AnimeSearchResponse( | ||||
|                     title, | ||||
|                     href, | ||||
|                     this.name, | ||||
|                     TvType.Anime, | ||||
|                     image, | ||||
|                     null, | ||||
|                     if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of( | ||||
|                         DubStatus.Dubbed | ||||
|                     ) else EnumSet.of(DubStatus.Subbed), | ||||
|                 ) | ||||
|             } | ||||
|         return ArrayList(search) | ||||
|     override suspend fun search(query: String): List<SearchResponse> { | ||||
|         return app.get("$mainUrl/buscar?q=$query", timeout = 120).document.select(".col-6").map { | ||||
|             val title = it.selectFirst(".animedtls p").text() | ||||
|             val href = it.selectFirst("a").attr("href") | ||||
|             val image = it.selectFirst(".animes img").attr("src") | ||||
|             AnimeSearchResponse( | ||||
|                 title, | ||||
|                 href, | ||||
|                 this.name, | ||||
|                 TvType.Anime, | ||||
|                 image, | ||||
|                 null, | ||||
|                 if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of( | ||||
|                     DubStatus.Dubbed | ||||
|                 ) else EnumSet.of(DubStatus.Subbed), | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun load(url: String): LoadResponse { | ||||
|  |  | |||
|  | @ -25,13 +25,12 @@ class FilmanProvider : MainAPI() { | |||
|         val categories = ArrayList<HomePageList>() | ||||
|         for (l in lists) { | ||||
|             val title = l.parent().select("h3").text() | ||||
|             val items = ArrayList<SearchResponse>() | ||||
|             for (i in l.select(".poster")) { | ||||
|             val items = l.select(".poster").map { i -> | ||||
|                 val name = i.select("a[href]").attr("title") | ||||
|                 val href = i.select("a[href]").attr("href") | ||||
|                 val poster = i.select("img[src]").attr("src") | ||||
|                 val year = l.select(".film_year").text().toIntOrNull() | ||||
|                 val returnValue = if (l.hasClass("series-list")) TvSeriesSearchResponse( | ||||
|                 if (l.hasClass("series-list")) TvSeriesSearchResponse( | ||||
|                     name, | ||||
|                     href, | ||||
|                     this.name, | ||||
|  | @ -47,7 +46,6 @@ class FilmanProvider : MainAPI() { | |||
|                     poster, | ||||
|                     year | ||||
|                 ) | ||||
|                 items.add(returnValue) | ||||
|             } | ||||
|             categories.add(HomePageList(title, items)) | ||||
|         } | ||||
|  | @ -62,29 +60,25 @@ class FilmanProvider : MainAPI() { | |||
|         val movies = lists[1].select(".item") | ||||
|         val series = lists[3].select(".item") | ||||
|         if (movies.isEmpty() && series.isEmpty()) return ArrayList() | ||||
|         fun getVideos(type: TvType, items: Elements): ArrayList<SearchResponse> { | ||||
|             val returnValue = ArrayList<SearchResponse>() | ||||
|             for (i in items) { | ||||
|         fun getVideos(type: TvType, items: Elements): List<SearchResponse> { | ||||
|             return items.map { i -> | ||||
|                 val href = i.attr("href") | ||||
|                 val img = i.selectFirst("> img").attr("src").replace("/thumb/", "/big/") | ||||
|                 val name = i.selectFirst(".title").text() | ||||
|                 if (type === TvType.TvSeries) { | ||||
|                     returnValue.add( | ||||
|                         TvSeriesSearchResponse( | ||||
|                             name, | ||||
|                             href, | ||||
|                             this.name, | ||||
|                             type, | ||||
|                             img, | ||||
|                             null, | ||||
|                             null | ||||
|                         ) | ||||
|                     TvSeriesSearchResponse( | ||||
|                         name, | ||||
|                         href, | ||||
|                         this.name, | ||||
|                         type, | ||||
|                         img, | ||||
|                         null, | ||||
|                         null | ||||
|                     ) | ||||
|                 } else { | ||||
|                     returnValue.add(MovieSearchResponse(name, href, this.name, type, img, null)) | ||||
|                     MovieSearchResponse(name, href, this.name, type, img, null) | ||||
|                 } | ||||
|             } | ||||
|             return returnValue | ||||
|         } | ||||
|         return getVideos(TvType.Movie, movies) + getVideos(TvType.TvSeries, series) | ||||
|     } | ||||
|  | @ -102,22 +96,17 @@ class FilmanProvider : MainAPI() { | |||
|             return MovieLoadResponse(title, url, name, TvType.Movie, data, posterUrl, year, plot) | ||||
|         } | ||||
|         title = document.selectFirst(".info").parent().select("h2").text() | ||||
|         val episodes = ArrayList<TvSeriesEpisode>() | ||||
|         for (episode in episodesElements) { | ||||
|         val episodes = episodesElements.mapNotNull { episode -> | ||||
|             val e = episode.text() | ||||
|             val regex = Regex("""\[s(\d{1,3})e(\d{1,3})]""").find(e) | ||||
|             if (regex != null) { | ||||
|                 val eid = regex.groups | ||||
|                 episodes.add( | ||||
|                     TvSeriesEpisode( | ||||
|                         e.split("]")[1].trim(), | ||||
|                         eid[1]?.value?.toInt(), | ||||
|                         eid[2]?.value?.toInt(), | ||||
|                         episode.attr("href"), | ||||
|                     ) | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
|             val regex = Regex("""\[s(\d{1,3})e(\d{1,3})]""").find(e) ?: return@mapNotNull null | ||||
|             val eid = regex.groups | ||||
|             TvSeriesEpisode( | ||||
|                 e.split("]")[1].trim(), | ||||
|                 eid[1]?.value?.toInt(), | ||||
|                 eid[2]?.value?.toInt(), | ||||
|                 episode.attr("href"), | ||||
|             ) | ||||
|         }.toMutableList() | ||||
|         episodes.sortBy { (it.season?.times(10000) ?: 0) + (it.episode ?: 0) } | ||||
|         return TvSeriesLoadResponse( | ||||
|             title, | ||||
|  |  | |||
|  | @ -19,17 +19,15 @@ class HDMProvider : MainAPI() { | |||
|         val response = app.get(url).text | ||||
|         val document = Jsoup.parse(response) | ||||
|         val items = document.select("div.col-md-2 > article > a") | ||||
|         if (items.isEmpty()) return ArrayList() | ||||
|         val returnValue = ArrayList<SearchResponse>() | ||||
|         for (i in items) { | ||||
|         if (items.isEmpty()) return emptyList() | ||||
| 
 | ||||
|         return items.map { i -> | ||||
|             val href = i.attr("href") | ||||
|             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, this.name, TvType.Movie, img, null)) | ||||
|             MovieSearchResponse(name, href, this.name, TvType.Movie, img, null) | ||||
|         } | ||||
| 
 | ||||
|         return returnValue | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun loadLinks( | ||||
|  | @ -72,7 +70,7 @@ class HDMProvider : MainAPI() { | |||
|     } | ||||
| 
 | ||||
|     override suspend fun getMainPage(): HomePageResponse { | ||||
|         val html = app.get("$mainUrl", timeout = 25).text | ||||
|         val html = app.get(mainUrl, timeout = 25).text | ||||
|         val document = Jsoup.parse(html) | ||||
|         val all = ArrayList<HomePageList>() | ||||
| 
 | ||||
|  |  | |||
|  | @ -110,36 +110,31 @@ class LookMovieProvider : MainAPI() { | |||
|     } | ||||
| 
 | ||||
|     override suspend fun search(query: String): List<SearchResponse> { | ||||
|         suspend fun search(query: String, isMovie: Boolean): ArrayList<SearchResponse> { | ||||
|         suspend fun search(query: String, isMovie: Boolean): List<SearchResponse> { | ||||
|             val url = "$mainUrl/${if (isMovie) "movies" else "shows"}/search/?q=$query" | ||||
|             val response = app.get(url).text | ||||
|             val document = Jsoup.parse(response) | ||||
| 
 | ||||
|             val items = document.select("div.flex-wrap-movielist > div.movie-item-style-1") | ||||
|             val returnValue = ArrayList<SearchResponse>() | ||||
|             items.forEach { item -> | ||||
|             return items.map { item -> | ||||
|                 val titleHolder = item.selectFirst("> div.mv-item-infor > h6 > a") | ||||
|                 val href = fixUrl(titleHolder.attr("href")) | ||||
|                 val name = titleHolder.text() | ||||
|                 val posterHolder = item.selectFirst("> div.image__placeholder > a") | ||||
|                 val poster = posterHolder.selectFirst("> img")?.attr("data-src") | ||||
|                 val year = posterHolder.selectFirst("> p.year")?.text()?.toIntOrNull() | ||||
| 
 | ||||
|                 returnValue.add( | ||||
|                     if (isMovie) { | ||||
|                         MovieSearchResponse( | ||||
|                             name, href, this.name, TvType.Movie, poster, year | ||||
|                         ) | ||||
|                     } else | ||||
|                         TvSeriesSearchResponse( | ||||
|                             name, href, this.name, TvType.TvSeries, poster, year, null | ||||
|                         ) | ||||
|                 ) | ||||
|                 if (isMovie) { | ||||
|                     MovieSearchResponse( | ||||
|                         name, href, this.name, TvType.Movie, poster, year | ||||
|                     ) | ||||
|                 } else | ||||
|                     TvSeriesSearchResponse( | ||||
|                         name, href, this.name, TvType.TvSeries, poster, year, null | ||||
|                     ) | ||||
|             } | ||||
|             return returnValue | ||||
|         } | ||||
| 
 | ||||
|         val movieList = search(query, true) | ||||
|         val movieList = search(query, true).toMutableList() | ||||
|         val seriesList = search(query, false) | ||||
|         movieList.addAll(seriesList) | ||||
|         return movieList | ||||
|  |  | |||
|  | @ -13,11 +13,11 @@ class FrenchStreamProvider : MainAPI() { | |||
|     override val lang = "fr" | ||||
|     override val supportedTypes = setOf(TvType.AnimeMovie, TvType.TvSeries, TvType.Movie) | ||||
| 
 | ||||
|     override suspend fun search(query: String): ArrayList<SearchResponse> { | ||||
|     override suspend fun search(query: String): List<SearchResponse> { | ||||
|         val link = "$mainUrl/?do=search&subaction=search&story=$query" | ||||
|         val soup = app.post(link).document | ||||
| 
 | ||||
|         return ArrayList(soup.select("div.short-in.nl").map { li -> | ||||
|         return soup.select("div.short-in.nl").map { li -> | ||||
|             val href = fixUrl(li.selectFirst("a.short-poster").attr("href")) | ||||
|             val poster = li.selectFirst("img")?.attr("src") | ||||
|             val title = li.selectFirst("> a.short-poster").text().toString().replace(". ", "") | ||||
|  | @ -46,7 +46,7 @@ class FrenchStreamProvider : MainAPI() { | |||
|                     year, | ||||
|                 ) | ||||
|             } | ||||
|         }) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun load(url: String): LoadResponse { | ||||
|  |  | |||
|  | @ -1,74 +1,67 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <navigation xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|             xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|             xmlns:tools="http://schemas.android.com/tools" | ||||
|             android:id="@+id/mobile_navigation" | ||||
|             app:startDestination="@+id/navigation_home"> | ||||
|         xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|         xmlns:tools="http://schemas.android.com/tools" | ||||
|         android:id="@+id/mobile_navigation" | ||||
|         app:startDestination="@+id/navigation_home"> | ||||
| 
 | ||||
|     <action android:id="@+id/global_to_navigation_results" | ||||
|     <action | ||||
|             android:id="@+id/global_to_navigation_results" | ||||
|             app:destination="@id/navigation_results" | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|             app:popEnterAnim="@anim/enter_anim" | ||||
|             app:popExitAnim="@anim/exit_anim" | ||||
|     > | ||||
|             app:popExitAnim="@anim/exit_anim"> | ||||
|         <argument | ||||
|                 android:name="url" | ||||
|                 app:argType="string"/> | ||||
|                 app:argType="string" /> | ||||
|         <argument | ||||
|                 android:name="apiName" | ||||
|                 app:argType="string" | ||||
|         /> | ||||
|                 app:argType="string" /> | ||||
|         <argument | ||||
|                 android:name="startAction" | ||||
|                 app:argType="integer" | ||||
|                 android:defaultValue="0" | ||||
|         /> | ||||
|                 android:defaultValue="0" /> | ||||
|         <argument | ||||
|                 android:name="startValue" | ||||
|                 app:argType="integer" | ||||
|                 android:defaultValue="0" | ||||
|         /> | ||||
|                 android:defaultValue="0" /> | ||||
|         <argument | ||||
|                 android:name="restart" | ||||
|                 app:argType="boolean" | ||||
|                 android:defaultValue="false" | ||||
|         /> | ||||
|                 android:defaultValue="false" /> | ||||
|     </action> | ||||
|     <action android:id="@+id/global_to_navigation_player" | ||||
|     <action | ||||
|             android:id="@+id/global_to_navigation_player" | ||||
|             app:destination="@id/navigation_player" | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|             app:popEnterAnim="@anim/enter_anim" | ||||
|             app:popExitAnim="@anim/exit_anim" | ||||
|     > | ||||
|             app:popExitAnim="@anim/exit_anim"> | ||||
|         <argument | ||||
|                 android:name="data" | ||||
|                 app:argType="string" | ||||
|                 android:defaultValue="@null" | ||||
|         /> | ||||
|                 android:defaultValue="@null" /> | ||||
|         <argument | ||||
|                 android:name="uriData" | ||||
|                 app:argType="string" | ||||
|                 android:defaultValue="@null" | ||||
|         /> | ||||
|                 android:defaultValue="@null" /> | ||||
|         <argument | ||||
|                 android:name="resumePosition" | ||||
|                 app:argType="long" | ||||
|                 android:defaultValue="0L" | ||||
|         /> | ||||
|                 android:defaultValue="0L" /> | ||||
|     </action> | ||||
| 
 | ||||
|     <action android:id="@+id/global_to_navigation_home" | ||||
|     <action | ||||
|             android:id="@+id/global_to_navigation_home" | ||||
|             app:destination="@id/navigation_home" | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|             app:popEnterAnim="@anim/enter_anim" | ||||
|             app:popExitAnim="@anim/exit_anim" | ||||
|     > | ||||
|     </action> | ||||
|             app:popExitAnim="@anim/exit_anim" /> | ||||
| 
 | ||||
|     <action android:id="@+id/global_to_navigation_subtitles" | ||||
|     <action | ||||
|             android:id="@+id/global_to_navigation_subtitles" | ||||
|             app:destination="@id/navigation_subtitles" | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|  | @ -77,11 +70,11 @@ | |||
|         <argument | ||||
|                 android:name="hide" | ||||
|                 app:argType="boolean" | ||||
|                 android:defaultValue="true" | ||||
|         /> | ||||
|                 android:defaultValue="true" /> | ||||
|     </action> | ||||
| 
 | ||||
|     <action android:id="@+id/global_to_navigation_chrome_subtitles" | ||||
|     <action | ||||
|             android:id="@+id/global_to_navigation_chrome_subtitles" | ||||
|             app:destination="@id/navigation_chrome_subtitles" | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|  | @ -90,11 +83,11 @@ | |||
|         <argument | ||||
|                 android:name="hide" | ||||
|                 app:argType="boolean" | ||||
|                 android:defaultValue="true" | ||||
|                 /> | ||||
|                 android:defaultValue="true" /> | ||||
|     </action> | ||||
| 
 | ||||
|     <action android:id="@+id/global_to_navigation_quick_search" | ||||
|     <action | ||||
|             android:id="@+id/global_to_navigation_quick_search" | ||||
|             app:destination="@id/navigation_quick_search" | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|  | @ -103,109 +96,143 @@ | |||
|         <argument | ||||
|                 android:name="mainapi" | ||||
|                 app:argType="boolean" | ||||
|                 android:defaultValue="true" | ||||
| 
 | ||||
|         /> | ||||
|                 android:defaultValue="true" /> | ||||
|         <argument | ||||
|         android:name="autosearch" | ||||
|         app:argType="string" | ||||
|         android:defaultValue="@null" | ||||
|         /> | ||||
|                 android:name="autosearch" | ||||
|                 app:argType="string" | ||||
|                 android:defaultValue="@null" /> | ||||
|     </action> | ||||
| 
 | ||||
|     <action android:id="@+id/global_to_navigation_settings" | ||||
|     <action | ||||
|             android:id="@+id/global_to_navigation_settings" | ||||
|             app:destination="@id/navigation_settings" | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|             app:popEnterAnim="@anim/enter_anim" | ||||
|             app:popExitAnim="@anim/exit_anim" | ||||
|     > | ||||
|     </action> | ||||
|             app:popExitAnim="@anim/exit_anim" /> | ||||
| 
 | ||||
|     <action android:id="@+id/global_to_navigation_downloads" | ||||
|     <action | ||||
|             android:id="@+id/global_to_navigation_downloads" | ||||
|             app:destination="@id/navigation_downloads" | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|             app:popEnterAnim="@anim/enter_anim" | ||||
|             app:popExitAnim="@anim/exit_anim" | ||||
|     > | ||||
|     </action> | ||||
|             app:popExitAnim="@anim/exit_anim" /> | ||||
| 
 | ||||
|     <action android:id="@+id/global_to_navigation_search" | ||||
|     <action | ||||
|             android:id="@+id/global_to_navigation_search" | ||||
|             app:destination="@id/navigation_search" | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|             app:popEnterAnim="@anim/enter_anim" | ||||
|             app:popExitAnim="@anim/exit_anim" | ||||
|     > | ||||
|     </action> | ||||
|             app:popExitAnim="@anim/exit_anim" /> | ||||
| 
 | ||||
|     <fragment | ||||
|             android:id="@+id/navigation_home" | ||||
|             android:name="com.lagradost.cloudstream3.ui.home.HomeFragment" | ||||
|             android:label="@string/title_home" | ||||
|             tools:layout="@layout/fragment_home"/> | ||||
|             tools:layout="@layout/fragment_home" | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|             app:popEnterAnim="@anim/enter_anim" | ||||
|             app:popExitAnim="@anim/exit_anim" /> | ||||
| 
 | ||||
|     <fragment | ||||
|             android:id="@+id/navigation_search" | ||||
|             android:name="com.lagradost.cloudstream3.ui.search.SearchFragment" | ||||
|             android:label="@string/title_search" | ||||
|             tools:layout="@layout/fragment_search"/> | ||||
|             tools:layout="@layout/fragment_search" | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|             app:popEnterAnim="@anim/enter_anim" | ||||
|             app:popExitAnim="@anim/exit_anim" /> | ||||
| 
 | ||||
|     <fragment | ||||
|             android:id="@+id/navigation_downloads" | ||||
|             android:name="com.lagradost.cloudstream3.ui.download.DownloadFragment" | ||||
|             android:label="@string/title_downloads" | ||||
|             tools:layout="@layout/fragment_downloads"> | ||||
|             tools:layout="@layout/fragment_downloads" | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|             app:popEnterAnim="@anim/enter_anim" | ||||
|             app:popExitAnim="@anim/exit_anim"> | ||||
| 
 | ||||
|         <action android:id="@+id/action_navigation_downloads_to_navigation_download_child" | ||||
|         <action | ||||
|                 android:id="@+id/action_navigation_downloads_to_navigation_download_child" | ||||
|                 app:destination="@id/navigation_download_child"> | ||||
|             <argument | ||||
|                     android:name="name" | ||||
|                     app:argType="string"/> | ||||
|                     app:argType="string" /> | ||||
|             <argument | ||||
|                     android:name="folder" | ||||
|                     app:argType="string" | ||||
|             /> | ||||
|                     app:argType="string" /> | ||||
|         </action> | ||||
|     </fragment> | ||||
|     <fragment | ||||
|             android:id="@+id/navigation_settings" | ||||
|             android:layout_height="match_parent" | ||||
|             android:name="com.lagradost.cloudstream3.ui.settings.SettingsFragment" | ||||
|             android:label="@string/title_settings"/> | ||||
|             android:label="@string/title_settings" | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|             app:popEnterAnim="@anim/enter_anim" | ||||
|             app:popExitAnim="@anim/exit_anim" /> | ||||
| 
 | ||||
|     <fragment | ||||
|             android:id="@+id/navigation_subtitles" | ||||
|             android:layout_height="match_parent" | ||||
|             android:name="com.lagradost.cloudstream3.ui.subtitles.SubtitlesFragment" | ||||
|             android:label="@string/subtitles_settings"/> | ||||
|             android:label="@string/subtitles_settings" | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|             app:popEnterAnim="@anim/enter_anim" | ||||
|             app:popExitAnim="@anim/exit_anim" /> | ||||
| 
 | ||||
|     <fragment | ||||
|             android:id="@+id/navigation_chrome_subtitles" | ||||
|             android:layout_height="match_parent" | ||||
|             android:name="com.lagradost.cloudstream3.ui.subtitles.ChromecastSubtitlesFragment" | ||||
|             android:label="@string/chromecast_subtitles_settings"/> | ||||
|             android:label="@string/chromecast_subtitles_settings" | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|             app:popEnterAnim="@anim/enter_anim" | ||||
|             app:popExitAnim="@anim/exit_anim" /> | ||||
| 
 | ||||
|     <fragment | ||||
|             android:id="@+id/navigation_quick_search" | ||||
|             android:layout_height="match_parent" | ||||
|             android:name="com.lagradost.cloudstream3.ui.quicksearch.QuickSearchFragment" | ||||
|             android:label="@string/search"/> | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|             app:popEnterAnim="@anim/enter_anim" | ||||
|             app:popExitAnim="@anim/exit_anim" | ||||
|             android:label="@string/search" /> | ||||
| 
 | ||||
|     <fragment | ||||
|             android:id="@+id/navigation_download_child" | ||||
|             android:layout_height="match_parent" | ||||
|             android:name="com.lagradost.cloudstream3.ui.download.DownloadChildFragment" | ||||
|             android:label="@string/title_settings"/> | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|             app:popEnterAnim="@anim/enter_anim" | ||||
|             app:popExitAnim="@anim/exit_anim" | ||||
|             android:label="@string/title_settings" /> | ||||
| 
 | ||||
|     <fragment | ||||
|             android:id="@+id/navigation_results" | ||||
|             android:layout_height="match_parent" | ||||
|             android:name="com.lagradost.cloudstream3.ui.result.ResultFragment"/> | ||||
|             android:name="com.lagradost.cloudstream3.ui.result.ResultFragment" | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|             app:popEnterAnim="@anim/enter_anim" | ||||
|             app:popExitAnim="@anim/exit_anim" /> | ||||
| 
 | ||||
|     <fragment | ||||
|             android:id="@+id/navigation_player" | ||||
|             android:layout_height="match_parent" | ||||
|             android:name="com.lagradost.cloudstream3.ui.player.GeneratorPlayer"/> | ||||
|             android:name="com.lagradost.cloudstream3.ui.player.GeneratorPlayer" | ||||
|             app:enterAnim="@anim/enter_anim" | ||||
|             app:exitAnim="@anim/exit_anim" | ||||
|             app:popEnterAnim="@anim/enter_anim" | ||||
|             app:popExitAnim="@anim/exit_anim" /> | ||||
| </navigation> | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue