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…
Reference in a new issue