mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
fixed #461
This commit is contained in:
parent
fd6eee635f
commit
44c7d5ff8c
46 changed files with 307 additions and 253 deletions
|
@ -231,24 +231,24 @@ abstract class MainAPI {
|
|||
open val vpnStatus = VPNStatus.None
|
||||
open val providerType = ProviderType.DirectProvider
|
||||
|
||||
open fun getMainPage(): HomePageResponse? {
|
||||
suspend open fun getMainPage(): HomePageResponse? {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
|
||||
open fun search(query: String): List<SearchResponse>? {
|
||||
suspend open fun search(query: String): List<SearchResponse>? {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
|
||||
open fun quickSearch(query: String): List<SearchResponse>? {
|
||||
suspend open fun quickSearch(query: String): List<SearchResponse>? {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
|
||||
open fun load(url: String): LoadResponse? {
|
||||
suspend open fun load(url: String): LoadResponse? {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
|
||||
/**Callback is fired once a link is found, will return true if method is executed successfully*/
|
||||
open fun loadLinks(
|
||||
suspend open fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -85,7 +85,7 @@ class AllAnimeProvider : MainAPI() {
|
|||
@JsonProperty("data") val data: Data
|
||||
)
|
||||
|
||||
override fun search(query: String): ArrayList<SearchResponse> {
|
||||
override suspend fun search(query: String): ArrayList<SearchResponse> {
|
||||
val link =
|
||||
"""$mainUrl/graphql?variables=%7B%22search%22%3A%7B%22allowAdult%22%3Afalse%2C%22query%22%3A%22$query%22%7D%2C%22limit%22%3A26%2C%22page%22%3A1%2C%22translationType%22%3A%22sub%22%7D&extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%229343797cc3d9e3f444e2d3b7db9a84d759b816a4d84512ea72d079f85bb96e98%22%7D%7D"""
|
||||
var res = app.get(link).text
|
||||
|
@ -123,7 +123,7 @@ class AllAnimeProvider : MainAPI() {
|
|||
)
|
||||
|
||||
|
||||
override fun load(url: String): LoadResponse? {
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
val rhino = Context.enter()
|
||||
rhino.initStandardObjects()
|
||||
rhino.optimizationLevel = -1
|
||||
|
@ -238,7 +238,7 @@ class AllAnimeProvider : MainAPI() {
|
|||
})
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -27,7 +27,7 @@ class AnimeFlickProvider : MainAPI() {
|
|||
TvType.ONA
|
||||
)
|
||||
|
||||
override fun search(query: String): ArrayList<SearchResponse> {
|
||||
override suspend fun search(query: String): ArrayList<SearchResponse> {
|
||||
val link = "https://animeflick.net/search.php?search=$query"
|
||||
val html = app.get(link).text
|
||||
val doc = Jsoup.parse(html)
|
||||
|
@ -48,7 +48,7 @@ class AnimeFlickProvider : MainAPI() {
|
|||
})
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val html = app.get(url).text
|
||||
val doc = Jsoup.parse(html)
|
||||
|
||||
|
@ -79,7 +79,7 @@ class AnimeFlickProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -54,7 +54,7 @@ class AnimePaheProvider : MainAPI() {
|
|||
TvType.ONA
|
||||
)
|
||||
|
||||
override fun getMainPage(): HomePageResponse {
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
data class Data(
|
||||
@JsonProperty("id") val id: Int,
|
||||
@JsonProperty("anime_id") val animeId: Int,
|
||||
|
@ -139,7 +139,7 @@ class AnimePaheProvider : MainAPI() {
|
|||
}
|
||||
|
||||
|
||||
override fun search(query: String): ArrayList<SearchResponse> {
|
||||
override suspend fun search(query: String): ArrayList<SearchResponse> {
|
||||
val url = "$mainUrl/api?m=search&l=8&q=$query"
|
||||
val headers = mapOf("referer" to "$mainUrl/")
|
||||
|
||||
|
@ -242,7 +242,7 @@ class AnimePaheProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse? {
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
return normalSafeApiCall {
|
||||
|
||||
val regex = Regex("""a/(\d+)\?slug=(.+)""")
|
||||
|
@ -541,7 +541,7 @@ class AnimePaheProvider : MainAPI() {
|
|||
return qualities
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -92,7 +92,7 @@ class DubbedAnimeProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun getMainPage(): HomePageResponse {
|
||||
override suspend fun getMainPage(): 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"
|
||||
|
@ -126,7 +126,7 @@ class DubbedAnimeProvider : MainAPI() {
|
|||
return href.replace("$mainUrl/", "")
|
||||
}
|
||||
|
||||
override fun quickSearch(query: String): List<SearchResponse> {
|
||||
override suspend fun quickSearch(query: String): List<SearchResponse> {
|
||||
val url = "$mainUrl/xz/searchgrid.php?p=1&limit=12&s=$query&_=$unixTime"
|
||||
val response = app.get(url).text
|
||||
val document = Jsoup.parse(response)
|
||||
|
@ -158,7 +158,7 @@ class DubbedAnimeProvider : MainAPI() {
|
|||
return returnValue
|
||||
}
|
||||
|
||||
override fun search(query: String): List<SearchResponse> {
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val url = "$mainUrl/search/$query"
|
||||
val response = app.get(url).text
|
||||
val document = Jsoup.parse(response)
|
||||
|
@ -193,7 +193,7 @@ class DubbedAnimeProvider : MainAPI() {
|
|||
return returnValue
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
@ -230,7 +230,7 @@ class DubbedAnimeProvider : MainAPI() {
|
|||
return true
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
if (getIsMovie(url)) {
|
||||
val realSlug = url.replace("movies/", "")
|
||||
val episode = getAnimeEpisode(realSlug, true)
|
||||
|
|
|
@ -37,7 +37,7 @@ class GogoanimeProvider : MainAPI() {
|
|||
TvType.ONA
|
||||
)
|
||||
|
||||
override fun getMainPage(): HomePageResponse {
|
||||
override suspend fun getMainPage(): 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\"",
|
||||
|
@ -95,7 +95,7 @@ class GogoanimeProvider : MainAPI() {
|
|||
return HomePageResponse(items)
|
||||
}
|
||||
|
||||
override fun search(query: String): ArrayList<SearchResponse> {
|
||||
override suspend fun search(query: String): ArrayList<SearchResponse> {
|
||||
val link = "$mainUrl/search.html?keyword=$query"
|
||||
val html = app.get(link).text
|
||||
val doc = Jsoup.parse(html)
|
||||
|
@ -129,7 +129,7 @@ class GogoanimeProvider : MainAPI() {
|
|||
return uri
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val link = getProperAnimeLink(url)
|
||||
val episodeloadApi = "https://ajax.gogo-load.com/ajax/load-list-episode"
|
||||
val html = app.get(link).text
|
||||
|
@ -232,7 +232,7 @@ class GogoanimeProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -14,7 +14,7 @@ class KawaiifuProvider : MainAPI() {
|
|||
|
||||
override val supportedTypes = setOf(TvType.Anime, TvType.AnimeMovie, TvType.ONA)
|
||||
|
||||
override fun getMainPage(): HomePageResponse {
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val items = ArrayList<HomePageList>()
|
||||
val resp = app.get(mainUrl).text
|
||||
|
||||
|
@ -58,7 +58,7 @@ class KawaiifuProvider : MainAPI() {
|
|||
}
|
||||
|
||||
|
||||
override fun search(query: String): ArrayList<SearchResponse> {
|
||||
override suspend fun search(query: String): ArrayList<SearchResponse> {
|
||||
val link = "$mainUrl/search-movie?keyword=${query}"
|
||||
val html = app.get(link).text
|
||||
val soup = Jsoup.parse(html)
|
||||
|
@ -80,7 +80,7 @@ class KawaiifuProvider : MainAPI() {
|
|||
})
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val html = app.get(url).text
|
||||
val soup = Jsoup.parse(html)
|
||||
|
||||
|
@ -110,7 +110,7 @@ class KawaiifuProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -45,7 +45,7 @@ class TenshiProvider : MainAPI() {
|
|||
}
|
||||
}*/
|
||||
|
||||
override fun getMainPage(): HomePageResponse {
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val items = ArrayList<HomePageList>()
|
||||
val soup = app.get(mainUrl, interceptor = ddosGuardKiller).document
|
||||
for (section in soup.select("#content > section")) {
|
||||
|
@ -152,7 +152,7 @@ class TenshiProvider : MainAPI() {
|
|||
// @JsonProperty("cen") var cen : String
|
||||
// )
|
||||
|
||||
// override fun quickSearch(query: String): ArrayList<SearchResponse>? {
|
||||
// override suspend fun quickSearch(query: String): ArrayList<SearchResponse>? {
|
||||
// if (!autoLoadToken()) return quickSearch(query)
|
||||
// val url = "$mainUrl/anime/search"
|
||||
// val response = khttp.post(
|
||||
|
@ -192,7 +192,7 @@ class TenshiProvider : MainAPI() {
|
|||
// return returnValue
|
||||
// }
|
||||
|
||||
override fun search(query: String): ArrayList<SearchResponse> {
|
||||
override suspend fun search(query: String): ArrayList<SearchResponse> {
|
||||
val url = "$mainUrl/anime"
|
||||
var document = app.get(
|
||||
url,
|
||||
|
@ -220,7 +220,7 @@ class TenshiProvider : MainAPI() {
|
|||
return ArrayList(returnValue)
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
var document = app.get(
|
||||
url,
|
||||
cookies = mapOf("loop-view" to "thumb"),
|
||||
|
@ -292,7 +292,7 @@ class TenshiProvider : MainAPI() {
|
|||
}
|
||||
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -22,7 +22,7 @@ class WatchCartoonOnlineProvider : MainAPI() {
|
|||
TvType.TvSeries
|
||||
)
|
||||
|
||||
override fun search(query: String): List<SearchResponse> {
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val url = "https://www.wcostream.com/search"
|
||||
|
||||
var response =
|
||||
|
@ -97,7 +97,7 @@ class WatchCartoonOnlineProvider : MainAPI() {
|
|||
return returnValue
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val isMovie = !url.contains("/anime/")
|
||||
val response = app.get(url).text
|
||||
val document = Jsoup.parse(response)
|
||||
|
@ -183,7 +183,7 @@ class WatchCartoonOnlineProvider : MainAPI() {
|
|||
val server: String,
|
||||
)
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -29,7 +29,7 @@ class WcoProvider : MainAPI() {
|
|||
TvType.ONA
|
||||
)
|
||||
|
||||
override fun getMainPage(): HomePageResponse {
|
||||
override suspend fun getMainPage(): 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"),
|
||||
|
@ -108,7 +108,7 @@ class WcoProvider : MainAPI() {
|
|||
return returnValue
|
||||
}
|
||||
|
||||
override fun search(query: String): List<SearchResponse> {
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val url = "$mainUrl/search"
|
||||
val response =
|
||||
app.get(url, params = mapOf("keyword" to query))
|
||||
|
@ -128,7 +128,7 @@ class WcoProvider : MainAPI() {
|
|||
return returnValue
|
||||
}
|
||||
|
||||
override fun quickSearch(query: String): List<SearchResponse> {
|
||||
override suspend fun quickSearch(query: String): List<SearchResponse> {
|
||||
val returnValue: ArrayList<SearchResponse> = ArrayList()
|
||||
|
||||
val response = JSONObject(
|
||||
|
@ -170,7 +170,7 @@ class WcoProvider : MainAPI() {
|
|||
return returnValue
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val response = app.get(url, timeout = 120).text
|
||||
val document = Jsoup.parse(response)
|
||||
|
||||
|
@ -216,7 +216,7 @@ class WcoProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -69,7 +69,7 @@ class ZoroProvider : MainAPI() {
|
|||
}
|
||||
|
||||
|
||||
override fun getMainPage(): HomePageResponse {
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val html = app.get("$mainUrl/home").text
|
||||
val document = Jsoup.parse(html)
|
||||
|
||||
|
@ -99,7 +99,7 @@ class ZoroProvider : MainAPI() {
|
|||
@JsonProperty("html") val html: String
|
||||
)
|
||||
|
||||
// override fun quickSearch(query: String): List<SearchResponse> {
|
||||
// override suspend fun quickSearch(query: String): List<SearchResponse> {
|
||||
// val url = "$mainUrl/ajax/search/suggest?keyword=${query}"
|
||||
// val html = mapper.readValue<Response>(khttp.get(url).text).html
|
||||
// val document = Jsoup.parse(html)
|
||||
|
@ -126,7 +126,7 @@ class ZoroProvider : MainAPI() {
|
|||
// }
|
||||
// }
|
||||
|
||||
override fun search(query: String): List<SearchResponse> {
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val link = "$mainUrl/search?keyword=$query"
|
||||
val html = app.get(link).text
|
||||
val document = Jsoup.parse(html)
|
||||
|
@ -172,7 +172,7 @@ class ZoroProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val html = app.get(url).text
|
||||
val document = Jsoup.parse(html)
|
||||
|
||||
|
@ -274,7 +274,7 @@ class ZoroProvider : MainAPI() {
|
|||
@JsonProperty("link") val link: String
|
||||
)
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -161,7 +161,7 @@ open class TmdbProvider : MainAPI() {
|
|||
)
|
||||
}
|
||||
|
||||
override fun getMainPage(): HomePageResponse {
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
|
||||
// SAME AS DISCOVER IT SEEMS
|
||||
// val popularSeries = tmdb.tvService().popular(1, "en-US").execute().body()?.results?.map {
|
||||
|
@ -220,7 +220,7 @@ open class TmdbProvider : MainAPI() {
|
|||
}
|
||||
|
||||
// Possible to add recommendations and such here.
|
||||
override fun load(url: String): LoadResponse? {
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
// https://www.themoviedb.org/movie/7445-brothers
|
||||
// https://www.themoviedb.org/tv/71914-the-wheel-of-time
|
||||
|
||||
|
@ -262,7 +262,7 @@ open class TmdbProvider : MainAPI() {
|
|||
|
||||
}
|
||||
|
||||
override fun search(query: String): List<SearchResponse>? {
|
||||
override suspend fun search(query: String): List<SearchResponse>? {
|
||||
return tmdb.searchService().multi(query, 1, "en-Us", "US", true).execute()
|
||||
.body()?.results?.mapNotNull {
|
||||
it.movie?.toSearchResponse() ?: it.tvShow?.toSearchResponse()
|
||||
|
|
|
@ -34,7 +34,7 @@ class AkwamProvider : MainAPI() {
|
|||
)
|
||||
}
|
||||
|
||||
override fun getMainPage(): HomePageResponse {
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
// Title, Url
|
||||
val moviesUrl = listOf(
|
||||
"Movies" to "$mainUrl/movies",
|
||||
|
@ -51,7 +51,7 @@ class AkwamProvider : MainAPI() {
|
|||
return HomePageResponse(pages)
|
||||
}
|
||||
|
||||
override fun search(query: String): List<SearchResponse> {
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val url = "$mainUrl/search?q=$query"
|
||||
val doc = app.get(url).document
|
||||
return doc.select("div.col-lg-auto").mapNotNull {
|
||||
|
@ -80,7 +80,7 @@ class AkwamProvider : MainAPI() {
|
|||
}
|
||||
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val doc = app.get(url).document
|
||||
val isMovie = url.contains("/movie/")
|
||||
val title = doc.select("h1.entry-title").text()
|
||||
|
@ -164,7 +164,7 @@ class AkwamProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -28,7 +28,7 @@ class AllMoviesForYouProvider : MainAPI() {
|
|||
TvType.TvSeries
|
||||
)
|
||||
|
||||
override fun search(query: String): List<SearchResponse> {
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val url = "$mainUrl/?s=$query"
|
||||
val document = app.get(url).document
|
||||
|
||||
|
@ -76,7 +76,7 @@ class AllMoviesForYouProvider : MainAPI() {
|
|||
return if (list.isEmpty()) null else list
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val type = getType(url)
|
||||
|
||||
val document = app.get(url).document
|
||||
|
@ -162,7 +162,7 @@ class AllMoviesForYouProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -112,7 +112,7 @@ class AsiaFlixProvider : MainAPI() {
|
|||
)
|
||||
}
|
||||
|
||||
override fun getMainPage(): HomePageResponse {
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val headers = mapOf("X-Requested-By" to "asiaflix-web")
|
||||
val response = app.get("$apiUrl/dashboard", headers = headers).text
|
||||
|
||||
|
@ -138,7 +138,7 @@ class AsiaFlixProvider : MainAPI() {
|
|||
@JsonProperty("url") val url: String?,
|
||||
)
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
@ -162,14 +162,14 @@ class AsiaFlixProvider : MainAPI() {
|
|||
return true
|
||||
}
|
||||
|
||||
override fun search(query: String): List<SearchResponse>? {
|
||||
override suspend fun search(query: String): List<SearchResponse>? {
|
||||
val headers = mapOf("X-Requested-By" to "asiaflix-web")
|
||||
val url = "$apiUrl/drama/search?q=$query"
|
||||
val response = app.get(url, headers = headers).text
|
||||
return mapper.readValue<List<Data>?>(response)?.map { it.toSearchResponse() }
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val headers = mapOf("X-Requested-By" to "asiaflix-web")
|
||||
val requestUrl = "$apiUrl/drama?id=${url.split("/").lastOrNull()}"
|
||||
val response = app.get(requestUrl, headers = headers).text
|
||||
|
|
|
@ -16,7 +16,7 @@ class DramaSeeProvider : MainAPI() {
|
|||
override val hasDownloadSupport = true
|
||||
override val supportedTypes = setOf(TvType.TvSeries, TvType.Movie)
|
||||
|
||||
override fun getMainPage(): HomePageResponse {
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val headers = mapOf("X-Requested-By" to "dramasee.net")
|
||||
val document = app.get(mainUrl, headers = headers).document
|
||||
val mainbody = document.getElementsByTag("body")
|
||||
|
@ -50,7 +50,7 @@ class DramaSeeProvider : MainAPI() {
|
|||
)
|
||||
}
|
||||
|
||||
override fun search(query: String): List<SearchResponse> {
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val url = "$mainUrl/search?q=$query"
|
||||
val html = app.get(url).document
|
||||
val document = html.getElementsByTag("body")
|
||||
|
@ -78,7 +78,7 @@ class DramaSeeProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val doc = app.get(url).document
|
||||
val body = doc.getElementsByTag("body")
|
||||
val inner = body?.select("div.series-info")
|
||||
|
@ -149,7 +149,7 @@ class DramaSeeProvider : MainAPI() {
|
|||
)
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -18,7 +18,7 @@ class FilmanProvider : MainAPI() {
|
|||
TvType.TvSeries
|
||||
)
|
||||
|
||||
override fun getMainPage(): HomePageResponse {
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val response = app.get(mainUrl).text
|
||||
val document = Jsoup.parse(response)
|
||||
val lists = document.select(".item-list,.series-list")
|
||||
|
@ -54,7 +54,7 @@ class FilmanProvider : MainAPI() {
|
|||
return HomePageResponse(categories)
|
||||
}
|
||||
|
||||
override fun search(query: String): List<SearchResponse> {
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val url = "$mainUrl/wyszukiwarka?phrase=$query"
|
||||
val response = app.get(url).text
|
||||
val document = Jsoup.parse(response)
|
||||
|
@ -79,7 +79,7 @@ class FilmanProvider : MainAPI() {
|
|||
return getVideos(TvType.Movie, movies) + getVideos(TvType.TvSeries, series)
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val response = app.get(url).text
|
||||
val document = Jsoup.parse(response)
|
||||
var title = document.select("span[itemprop=title]").text()
|
||||
|
@ -109,7 +109,7 @@ class FilmanProvider : MainAPI() {
|
|||
return TvSeriesLoadResponse(title, url, name, TvType.TvSeries, episodes, posterUrl, year, plot)
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -14,7 +14,7 @@ class HDMProvider : MainAPI() {
|
|||
TvType.Movie,
|
||||
)
|
||||
|
||||
override fun search(query: String): List<SearchResponse> {
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val url = "$mainUrl/search/$query"
|
||||
val response = app.get(url).text
|
||||
val document = Jsoup.parse(response)
|
||||
|
@ -32,7 +32,7 @@ class HDMProvider : MainAPI() {
|
|||
return returnValue
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
@ -55,7 +55,7 @@ class HDMProvider : MainAPI() {
|
|||
return true
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse? {
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
val response = app.get(url).text
|
||||
val document = Jsoup.parse(response)
|
||||
val title = document.selectFirst("h2.movieTitle")?.text() ?: throw ErrorLoadingException("No Data Found")
|
||||
|
@ -71,7 +71,7 @@ class HDMProvider : MainAPI() {
|
|||
)
|
||||
}
|
||||
|
||||
override fun getMainPage(): HomePageResponse {
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val html = app.get("$mainUrl", timeout = 25).text
|
||||
val document = Jsoup.parse(html)
|
||||
val all = ArrayList<HomePageList>()
|
||||
|
|
|
@ -14,7 +14,7 @@ class IHaveNoTvProvider : MainAPI() {
|
|||
|
||||
override val supportedTypes = setOf(TvType.Documentary)
|
||||
|
||||
override fun getMainPage(): HomePageResponse {
|
||||
override suspend fun getMainPage(): 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(
|
||||
|
@ -67,7 +67,7 @@ class IHaveNoTvProvider : MainAPI() {
|
|||
return HomePageResponse(items)
|
||||
}
|
||||
|
||||
override fun search(query: String): ArrayList<SearchResponse> {
|
||||
override suspend fun search(query: String): ArrayList<SearchResponse> {
|
||||
val url = """$mainUrl/search/${URLEncoder.encode(query, "UTF-8")}"""
|
||||
val response = app.get(url).text
|
||||
val soup = Jsoup.parse(response)
|
||||
|
@ -101,7 +101,7 @@ class IHaveNoTvProvider : MainAPI() {
|
|||
return ArrayList(searchResults.values)
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val isSeries = url.contains("/series/")
|
||||
val html = app.get(url).text
|
||||
val soup = Jsoup.parse(html)
|
||||
|
@ -190,7 +190,7 @@ class IHaveNoTvProvider : MainAPI() {
|
|||
) else (episodes?.first() as MovieLoadResponse)
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -19,7 +19,7 @@ class KdramaHoodProvider : MainAPI() {
|
|||
override val hasDownloadSupport = true
|
||||
override val supportedTypes = setOf(TvType.TvSeries, TvType.Movie)
|
||||
|
||||
override fun getMainPage(): HomePageResponse {
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val doc = app.get("$mainUrl/home2").document
|
||||
val home = ArrayList<HomePageList>()
|
||||
|
||||
|
@ -59,7 +59,7 @@ class KdramaHoodProvider : MainAPI() {
|
|||
return HomePageResponse(home.filter { it.list.isNotEmpty() })
|
||||
}
|
||||
|
||||
override fun search(query: String): List<SearchResponse> {
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val url = "$mainUrl/?s=$query"
|
||||
val html = app.get(url).document
|
||||
val document = html.getElementsByTag("body")
|
||||
|
@ -87,7 +87,7 @@ class KdramaHoodProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val doc = app.get(url).document
|
||||
val inner = doc.selectFirst("div.central")
|
||||
|
||||
|
@ -180,7 +180,7 @@ class KdramaHoodProvider : MainAPI() {
|
|||
)
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -64,7 +64,7 @@ class LookMovieProvider : MainAPI() {
|
|||
@JsonProperty("season") var season: String,
|
||||
)
|
||||
|
||||
override fun quickSearch(query: String): List<SearchResponse> {
|
||||
override suspend fun quickSearch(query: String): List<SearchResponse> {
|
||||
val movieUrl = "$mainUrl/api/v1/movies/search/?q=$query"
|
||||
val movieResponse = app.get(movieUrl).text
|
||||
val movies = mapper.readValue<LookMovieSearchResultRoot>(movieResponse).result
|
||||
|
@ -109,7 +109,7 @@ class LookMovieProvider : MainAPI() {
|
|||
return returnValue
|
||||
}
|
||||
|
||||
override fun search(query: String): List<SearchResponse> {
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
fun search(query: String, isMovie: Boolean): ArrayList<SearchResponse> {
|
||||
val url = "$mainUrl/${if (isMovie) "movies" else "shows"}/search/?q=$query"
|
||||
val response = app.get(url).text
|
||||
|
@ -174,7 +174,7 @@ class LookMovieProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
@ -198,7 +198,7 @@ class LookMovieProvider : MainAPI() {
|
|||
return true
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse? {
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
val response = app.get(url).text
|
||||
val document = Jsoup.parse(response)
|
||||
val isMovie = url.contains("/movies/")
|
||||
|
|
|
@ -28,11 +28,11 @@ class MeloMovieProvider : MainAPI() {
|
|||
|
||||
data class MeloMovieLink(val name: String, val link: String)
|
||||
|
||||
override fun quickSearch(query: String): List<SearchResponse> {
|
||||
override suspend fun quickSearch(query: String): List<SearchResponse> {
|
||||
return search(query)
|
||||
}
|
||||
|
||||
override fun search(query: String): List<SearchResponse> {
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val url = "$mainUrl/movie/search/?name=$query"
|
||||
val returnValue: ArrayList<SearchResponse> = ArrayList()
|
||||
val response = app.get(url).text
|
||||
|
@ -98,7 +98,7 @@ class MeloMovieProvider : MainAPI() {
|
|||
return parsed.toJson()
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
@ -111,7 +111,7 @@ class MeloMovieProvider : MainAPI() {
|
|||
return true
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse? {
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
val response = app.get(url).text
|
||||
|
||||
//backdrop = imgurl
|
||||
|
|
|
@ -19,7 +19,7 @@ class PelisplusHDProvider:MainAPI() {
|
|||
TvType.TvSeries,
|
||||
TvType.Anime,
|
||||
)
|
||||
override fun getMainPage(): HomePageResponse {
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val items = ArrayList<HomePageList>()
|
||||
val urls = listOf(
|
||||
Pair("$mainUrl/peliculas", "Peliculas"),
|
||||
|
@ -55,7 +55,7 @@ class PelisplusHDProvider:MainAPI() {
|
|||
return HomePageResponse(items)
|
||||
}
|
||||
|
||||
override fun search(query: String): List<SearchResponse> {
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val url = "https://pelisplushd.net/search?s=${query}"
|
||||
val html = app.get(url).text
|
||||
val document = Jsoup.parse(html)
|
||||
|
@ -89,7 +89,7 @@ class PelisplusHDProvider:MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse? {
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
val html = app.get(url).text
|
||||
val soup = Jsoup.parse(html)
|
||||
|
||||
|
@ -146,7 +146,7 @@ class PelisplusHDProvider:MainAPI() {
|
|||
else -> null
|
||||
}
|
||||
}
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -35,7 +35,7 @@ open class PelisplusProviderTemplate : MainAPI() {
|
|||
|
||||
// Searching returns a SearchResponse, which can be one of the following: AnimeSearchResponse, MovieSearchResponse, TorrentSearchResponse, TvSeriesSearchResponse
|
||||
// Each of the classes requires some different data, but always has some critical things like name, poster and url.
|
||||
override fun search(query: String): ArrayList<SearchResponse> {
|
||||
override suspend fun search(query: String): ArrayList<SearchResponse> {
|
||||
// Simply looking at devtools network is enough to spot a request like:
|
||||
// https://vidembed.cc/search.html?keyword=neverland where neverland is the query, can be written as below.
|
||||
val link = "$mainUrl/search.html?keyword=$query"
|
||||
|
@ -68,7 +68,7 @@ open class PelisplusProviderTemplate : MainAPI() {
|
|||
|
||||
// Load, like the name suggests loads the info page, where all the episodes and data usually is.
|
||||
// Like search you should return either of: AnimeLoadResponse, MovieLoadResponse, TorrentLoadResponse, TvSeriesLoadResponse.
|
||||
override fun load(url: String): LoadResponse? {
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
// Gets the url returned from searching.
|
||||
val html = app.get(url).text
|
||||
val soup = Jsoup.parse(html)
|
||||
|
@ -147,7 +147,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 fun getMainPage(): HomePageResponse {
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val urls = homePageUrlList
|
||||
val homePageList = ArrayList<HomePageList>()
|
||||
// .pmap {} is used to fetch the different pages in parallel
|
||||
|
@ -201,7 +201,7 @@ open class PelisplusProviderTemplate : MainAPI() {
|
|||
// loadLinks gets the raw .mp4 or .m3u8 urls from the data parameter in the episodes class generated in load()
|
||||
// See TvSeriesEpisode(...) in this provider.
|
||||
// The data are usually links, but can be any other string to help aid loading the links.
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
// These callbacks are functions you should call when you get a link to a subtitle file or media file.
|
||||
|
|
|
@ -16,7 +16,7 @@ class PinoyHDXyzProvider : MainAPI() {
|
|||
override val hasQuickSearch = false
|
||||
|
||||
|
||||
override fun getMainPage(): HomePageResponse {
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val all = ArrayList<HomePageList>()
|
||||
val document = app.get(mainUrl, referer = mainUrl).document
|
||||
val mainbody = document.getElementsByTag("body")
|
||||
|
@ -65,7 +65,7 @@ class PinoyHDXyzProvider : MainAPI() {
|
|||
return HomePageResponse(all)
|
||||
}
|
||||
|
||||
override fun search(query: String): List<SearchResponse> {
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val url = "$mainUrl/search/?q=${query.replace(" ", "+")}"
|
||||
val document = app.get(url).document.select("div.portfolio-thumb")
|
||||
return document?.mapNotNull {
|
||||
|
@ -88,7 +88,7 @@ class PinoyHDXyzProvider : MainAPI() {
|
|||
}?.distinctBy { c -> c.url } ?: listOf()
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val doc = app.get(url).document
|
||||
val body = doc.getElementsByTag("body")
|
||||
val inner = body?.select("div.info")
|
||||
|
@ -203,7 +203,7 @@ class PinoyHDXyzProvider : MainAPI() {
|
|||
return MovieLoadResponse(title, url, this.name, tvtype, streamLinks, poster, year, descript, null, null)
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -16,7 +16,7 @@ class PinoyMoviePediaProvider : MainAPI() {
|
|||
override val hasMainPage = true
|
||||
override val hasQuickSearch = false
|
||||
|
||||
override fun getMainPage(): HomePageResponse {
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val all = ArrayList<HomePageList>()
|
||||
val document = app.get(mainUrl).document
|
||||
val mainbody = document.getElementsByTag("body")
|
||||
|
@ -72,7 +72,7 @@ class PinoyMoviePediaProvider : MainAPI() {
|
|||
return HomePageResponse(all.filter { a -> a.list.isNotEmpty() })
|
||||
}
|
||||
|
||||
override fun search(query: String): List<SearchResponse> {
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val url = "$mainUrl/?s=${query}"
|
||||
val document = app.get(url).document.selectFirst("div.search-page")
|
||||
?.select("div.result-item")
|
||||
|
@ -97,7 +97,7 @@ class PinoyMoviePediaProvider : MainAPI() {
|
|||
}?.distinctBy { c -> c.url } ?: listOf()
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val doc = app.get(url).document
|
||||
val body = doc.getElementsByTag("body")
|
||||
val inner = body?.select("div.sheader")
|
||||
|
@ -171,7 +171,7 @@ class PinoyMoviePediaProvider : MainAPI() {
|
|||
return MovieLoadResponse(title, url, this.name, TvType.Movie, streamlinks, poster, year, descript, null, null)
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -58,7 +58,7 @@ class PinoyMoviesEsProvider : MainAPI() {
|
|||
}
|
||||
return all
|
||||
}
|
||||
override fun getMainPage(): HomePageResponse {
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val all = ArrayList<HomePageList>()
|
||||
val html = app.get(mainUrl).text
|
||||
val document = Jsoup.parse(html)
|
||||
|
@ -87,7 +87,7 @@ class PinoyMoviesEsProvider : MainAPI() {
|
|||
return HomePageResponse(all)
|
||||
}
|
||||
|
||||
override fun search(query: String): List<SearchResponse> {
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val url = "$mainUrl/?s=${query}"
|
||||
val html = app.get(url, interceptor = DdosGuardKiller(true)).text
|
||||
//Log.i(this.name, "Result => (html) ${Jsoup.parse(html).getElementsByTag("body")}")
|
||||
|
@ -115,7 +115,7 @@ class PinoyMoviesEsProvider : MainAPI() {
|
|||
return listOf()
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val response = app.get(url).text
|
||||
val doc = Jsoup.parse(response)
|
||||
val body = doc.getElementsByTag("body")
|
||||
|
@ -185,7 +185,7 @@ class PinoyMoviesEsProvider : MainAPI() {
|
|||
return MovieLoadResponse(title, url, this.name, TvType.Movie, streamlinks, poster, year, descript, null, null)
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package com.lagradost.cloudstream3.movieproviders
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.fasterxml.jackson.module.kotlin.readValue
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.network.WebViewResolver
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.M3u8Helper
|
||||
import com.lagradost.cloudstream3.utils.getQualityFromName
|
||||
|
@ -26,35 +28,7 @@ class SflixProvider(providerUrl: String, providerName: String) : MainAPI() {
|
|||
)
|
||||
override val vpnStatus = VPNStatus.None
|
||||
|
||||
private fun Element.toSearchResult(): SearchResponse {
|
||||
val img = this.select("img")
|
||||
val title = img.attr("title")
|
||||
val posterUrl = img.attr("data-src")
|
||||
val href = fixUrl(this.select("a").attr("href"))
|
||||
val isMovie = href.contains("/movie/")
|
||||
return if (isMovie) {
|
||||
MovieSearchResponse(
|
||||
title,
|
||||
href,
|
||||
this@SflixProvider.name,
|
||||
TvType.Movie,
|
||||
posterUrl,
|
||||
null
|
||||
)
|
||||
} else {
|
||||
TvSeriesSearchResponse(
|
||||
title,
|
||||
href,
|
||||
this@SflixProvider.name,
|
||||
TvType.Movie,
|
||||
posterUrl,
|
||||
null,
|
||||
null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMainPage(): HomePageResponse {
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val html = app.get("$mainUrl/home").text
|
||||
val document = Jsoup.parse(html)
|
||||
|
||||
|
@ -84,7 +58,7 @@ class SflixProvider(providerUrl: String, providerName: String) : MainAPI() {
|
|||
return HomePageResponse(all)
|
||||
}
|
||||
|
||||
override fun search(query: String): List<SearchResponse> {
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val url = "$mainUrl/search/${query.replace(" ", "-")}"
|
||||
val html = app.get(url).text
|
||||
val document = Jsoup.parse(html)
|
||||
|
@ -119,7 +93,7 @@ class SflixProvider(providerUrl: String, providerName: String) : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val document = app.get(url).document
|
||||
|
||||
val details = document.select("div.detail_page-watch")
|
||||
|
@ -151,15 +125,16 @@ class SflixProvider(providerUrl: String, providerName: String) : MainAPI() {
|
|||
val episodes = app.get(episodesUrl).text
|
||||
|
||||
// Supported streams, they're identical
|
||||
val sourceId = Jsoup.parse(episodes).select("a").firstOrNull {
|
||||
it.select("span").text().trim().equals("RapidStream", ignoreCase = true)
|
||||
|| it.select("span").text().trim().equals("Vidcloud", ignoreCase = true)
|
||||
}?.attr("data-id")
|
||||
val sourceIds = Jsoup.parse(episodes).select("a").mapNotNull { element ->
|
||||
val sourceId = element.attr("data-id") ?: return@mapNotNull null
|
||||
if(element.select("span")?.text()?.trim()?.isValidServer() == true) {
|
||||
"$url.$sourceId".replace("/movie/", "/watch-movie/")
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
val webViewUrl =
|
||||
"$url${sourceId?.let { ".$it" } ?: ""}".replace("/movie/", "/watch-movie/")
|
||||
|
||||
return newMovieLoadResponse(title, url, TvType.Movie, webViewUrl) {
|
||||
return newMovieLoadResponse(title, url, TvType.Movie, sourceIds.toJson()) {
|
||||
this.year = year
|
||||
this.posterUrl = posterUrl
|
||||
this.plot = plot
|
||||
|
@ -186,7 +161,8 @@ class SflixProvider(providerUrl: String, providerName: String) : MainAPI() {
|
|||
episode++
|
||||
|
||||
val episodeNum =
|
||||
(it.select("div.episode-number")?.text() ?: episodeTitle).let { str ->
|
||||
(it.select("div.episode-number")?.text()
|
||||
?: episodeTitle).let { str ->
|
||||
Regex("""\d+""").find(str)?.groupValues?.firstOrNull()
|
||||
?.toIntOrNull()
|
||||
} ?: episode
|
||||
|
@ -231,64 +207,102 @@ class SflixProvider(providerUrl: String, providerName: String) : MainAPI() {
|
|||
@JsonProperty("tracks") val tracks: List<Tracks?>?
|
||||
)
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
|
||||
// To transfer url:::id
|
||||
val split = data.split(":::")
|
||||
// Only used for tv series
|
||||
val url = if (split.size == 2) {
|
||||
val episodesUrl = "$mainUrl/ajax/v2/episode/servers/${split[1]}"
|
||||
val urls = (tryParseJson<Pair<String, String>>(data)?.let { (prefix, server) ->
|
||||
val episodesUrl = "$mainUrl/ajax/v2/episode/servers/$server"
|
||||
val episodes = app.get(episodesUrl).text
|
||||
|
||||
// Supported streams, they're identical
|
||||
val sourceId = Jsoup.parse(episodes).select("a").firstOrNull {
|
||||
it.select("span").text().trim().equals("RapidStream", ignoreCase = true)
|
||||
|| it.select("span").text().trim().equals("Vidcloud", ignoreCase = true)
|
||||
}?.attr("data-id")
|
||||
Jsoup.parse(episodes).select("a").mapNotNull { element ->
|
||||
val id = element?.attr("data-id") ?: return@mapNotNull null
|
||||
if(element.select("span")?.text()?.trim()?.isValidServer() == true) {
|
||||
"$prefix.$id".replace("/tv/", "/watch-tv/")
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
} ?: tryParseJson<List<String>>(data))?.distinct()
|
||||
|
||||
"${split[0]}${sourceId?.let { ".$it" } ?: ""}".replace("/tv/", "/watch-tv/")
|
||||
} else {
|
||||
data
|
||||
urls?.pmap { url ->
|
||||
println("FETCHING URL $url")
|
||||
val sources = app.get(
|
||||
url,
|
||||
interceptor = WebViewResolver(
|
||||
Regex("""/getSources"""),
|
||||
)
|
||||
).text
|
||||
|
||||
val mapped = parseJson<SourceObject>(sources)
|
||||
|
||||
mapped.tracks?.forEach {
|
||||
it?.toSubtitleFile()?.let { subtitleFile ->
|
||||
subtitleCallback.invoke(subtitleFile)
|
||||
}
|
||||
}
|
||||
|
||||
listOf(
|
||||
mapped.sources to "",
|
||||
mapped.sources1 to "source 2",
|
||||
mapped.sources2 to "source 3",
|
||||
mapped.sourcesBackup to "source backup"
|
||||
).forEach { subList ->
|
||||
subList.first?.forEach {
|
||||
it?.toExtractorLink(this, subList.second)?.forEach(callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val sources = app.get(
|
||||
url,
|
||||
interceptor = WebViewResolver(
|
||||
Regex("""/getSources""")
|
||||
return !urls.isNullOrEmpty()
|
||||
}
|
||||
|
||||
private fun Element.toSearchResult(): SearchResponse {
|
||||
val img = this.select("img")
|
||||
val title = img.attr("title")
|
||||
val posterUrl = img.attr("data-src")
|
||||
val href = fixUrl(this.select("a").attr("href"))
|
||||
val isMovie = href.contains("/movie/")
|
||||
return if (isMovie) {
|
||||
MovieSearchResponse(
|
||||
title,
|
||||
href,
|
||||
this@SflixProvider.name,
|
||||
TvType.Movie,
|
||||
posterUrl,
|
||||
null
|
||||
)
|
||||
} else {
|
||||
TvSeriesSearchResponse(
|
||||
title,
|
||||
href,
|
||||
this@SflixProvider.name,
|
||||
TvType.Movie,
|
||||
posterUrl,
|
||||
null,
|
||||
null
|
||||
)
|
||||
).text
|
||||
|
||||
val mapped = mapper.readValue<SourceObject>(sources)
|
||||
|
||||
mapped.tracks?.forEach {
|
||||
it?.toSubtitleFile()?.let { subtitleFile ->
|
||||
subtitleCallback.invoke(subtitleFile)
|
||||
}
|
||||
}
|
||||
|
||||
listOf(
|
||||
mapped.sources to "source 1",
|
||||
mapped.sources1 to "source 2",
|
||||
mapped.sources2 to "source 3",
|
||||
mapped.sourcesBackup to "source backup"
|
||||
).forEach { subList ->
|
||||
subList.first?.forEach {
|
||||
it?.toExtractorLink(this, subList.second)?.forEach(callback)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
// For re-use in Zoro
|
||||
fun String?.isValidServer(): Boolean {
|
||||
if (this.isNullOrEmpty()) return false
|
||||
if (this.equals("UpCloud", ignoreCase = true) || this.equals(
|
||||
"Vidcloud",
|
||||
ignoreCase = true
|
||||
) || this.equals("RapidStream", ignoreCase = true)
|
||||
) return true
|
||||
return true
|
||||
}
|
||||
|
||||
// For re-use in Zoro
|
||||
fun Sources.toExtractorLink(caller: MainAPI, name: String): List<ExtractorLink>? {
|
||||
return this.file?.let { file ->
|
||||
//println("FILE::: $file")
|
||||
val isM3u8 = URI(this.file).path.endsWith(".m3u8") || this.type.equals(
|
||||
"hls",
|
||||
ignoreCase = true
|
||||
|
@ -296,6 +310,7 @@ class SflixProvider(providerUrl: String, providerName: String) : MainAPI() {
|
|||
if (isM3u8) {
|
||||
M3u8Helper().m3u8Generation(M3u8Helper.M3u8Stream(this.file, null), true)
|
||||
.map { stream ->
|
||||
//println("stream: ${stream.quality} at ${stream.streamUrl}")
|
||||
val qualityString = if ((stream.quality ?: 0) == 0) label
|
||||
?: "" else "${stream.quality}p"
|
||||
ExtractorLink(
|
||||
|
|
|
@ -28,7 +28,7 @@ class TrailersTwoProvider : TmdbProvider() {
|
|||
TvType.Cartoon
|
||||
)
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -13,7 +13,7 @@ class VMoveeProvider : MainAPI() {
|
|||
|
||||
override val supportedTypes = setOf(TvType.Movie)
|
||||
|
||||
override fun search(query: String): List<SearchResponse> {
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val url = "$mainUrl/?s=$query"
|
||||
val response = app.get(url).text
|
||||
val document = Jsoup.parse(response)
|
||||
|
@ -60,7 +60,7 @@ class VMoveeProvider : MainAPI() {
|
|||
val data: List<ReeoovAPIData>,
|
||||
)
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
@ -108,7 +108,7 @@ class VMoveeProvider : MainAPI() {
|
|||
return true
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val response = app.get(url).text
|
||||
val document = Jsoup.parse(response)
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ class VfFilmProvider : MainAPI() {
|
|||
|
||||
override val supportedTypes = setOf(TvType.Movie)
|
||||
|
||||
override fun search(query: String): List<SearchResponse> {
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val url = "$mainUrl/?s=$query"
|
||||
val response = app.get(url).text
|
||||
val document = Jsoup.parse(response)
|
||||
|
@ -39,7 +39,7 @@ class VfFilmProvider : MainAPI() {
|
|||
return returnValue
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
@ -70,7 +70,7 @@ class VfFilmProvider : MainAPI() {
|
|||
return vudoUrl
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val response = app.get(url).text
|
||||
val document = Jsoup.parse(response)
|
||||
val title = document?.selectFirst("div.SubTitle")?.text()
|
||||
|
|
|
@ -17,7 +17,7 @@ class VfSerieProvider : MainAPI() {
|
|||
|
||||
override val supportedTypes = setOf(TvType.TvSeries)
|
||||
|
||||
override fun search(query: String): List<SearchResponse> {
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val url = "$mainUrl/?s=$query"
|
||||
val response = app.get(url).text
|
||||
val document = Jsoup.parse(response)
|
||||
|
@ -52,7 +52,7 @@ class VfSerieProvider : MainAPI() {
|
|||
.toString() // direct mp4 link, https://m5.vudeo.net/2vp3xgpw2avjdohilpfbtyuxzzrqzuh4z5yxvztral5k3rjnba6f4byj3saa/v.mp4 for exemple
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
@ -95,7 +95,7 @@ class VfSerieProvider : MainAPI() {
|
|||
return true
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val response = app.get(url).text
|
||||
val document = Jsoup.parse(response)
|
||||
val title =
|
||||
|
|
|
@ -33,7 +33,7 @@ open class VidstreamProviderTemplate : MainAPI() {
|
|||
|
||||
// Searching returns a SearchResponse, which can be one of the following: AnimeSearchResponse, MovieSearchResponse, TorrentSearchResponse, TvSeriesSearchResponse
|
||||
// Each of the classes requires some different data, but always has some critical things like name, poster and url.
|
||||
override fun search(query: String): ArrayList<SearchResponse> {
|
||||
override suspend fun search(query: String): ArrayList<SearchResponse> {
|
||||
// Simply looking at devtools network is enough to spot a request like:
|
||||
// https://vidembed.cc/search.html?keyword=neverland where neverland is the query, can be written as below.
|
||||
val link = "$mainUrl/search.html?keyword=$query"
|
||||
|
@ -66,7 +66,7 @@ open class VidstreamProviderTemplate : MainAPI() {
|
|||
|
||||
// Load, like the name suggests loads the info page, where all the episodes and data usually is.
|
||||
// Like search you should return either of: AnimeLoadResponse, MovieLoadResponse, TorrentLoadResponse, TvSeriesLoadResponse.
|
||||
override fun load(url: String): LoadResponse? {
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
// Gets the url returned from searching.
|
||||
val html = app.get(url).text
|
||||
val soup = Jsoup.parse(html)
|
||||
|
@ -144,7 +144,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 fun getMainPage(): HomePageResponse {
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val urls = homePageUrlList
|
||||
val homePageList = ArrayList<HomePageList>()
|
||||
// .pmap {} is used to fetch the different pages in parallel
|
||||
|
@ -198,7 +198,7 @@ open class VidstreamProviderTemplate : MainAPI() {
|
|||
// loadLinks gets the raw .mp4 or .m3u8 urls from the data parameter in the episodes class generated in load()
|
||||
// See TvSeriesEpisode(...) in this provider.
|
||||
// The data are usually links, but can be any other string to help aid loading the links.
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
// These callbacks are functions you should call when you get a link to a subtitle file or media file.
|
||||
|
|
|
@ -16,7 +16,7 @@ class WatchAsianProvider : MainAPI() {
|
|||
override val hasDownloadSupport = true
|
||||
override val supportedTypes = setOf(TvType.TvSeries, TvType.Movie)
|
||||
|
||||
override fun getMainPage(): HomePageResponse {
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val headers = mapOf("X-Requested-By" to mainUrl)
|
||||
val doc = app.get(mainUrl, headers = headers).document
|
||||
val rowPair = mutableListOf<Pair<String, String>>()
|
||||
|
@ -64,7 +64,7 @@ class WatchAsianProvider : MainAPI() {
|
|||
)
|
||||
}
|
||||
|
||||
override fun search(query: String): List<SearchResponse> {
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val url = "$mainUrl/search?type=movies&keyword=$query"
|
||||
val document = app.get(url).document.getElementsByTag("body")
|
||||
.select("div.block.tab-container > div > ul > li") ?: return listOf()
|
||||
|
@ -89,7 +89,7 @@ class WatchAsianProvider : MainAPI() {
|
|||
}.distinctBy { a -> a.url }
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val body = app.get(url).document
|
||||
// Declare vars
|
||||
val isDramaDetail = url.contains("/drama-detail/")
|
||||
|
@ -163,7 +163,7 @@ class WatchAsianProvider : MainAPI() {
|
|||
)
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -13,7 +13,7 @@ class FrenchStreamProvider : MainAPI() {
|
|||
override val lang = "fr"
|
||||
override val supportedTypes = setOf(TvType.AnimeMovie, TvType.TvSeries, TvType.Movie)
|
||||
|
||||
override fun search(query: String): ArrayList<SearchResponse> {
|
||||
override suspend fun search(query: String): ArrayList<SearchResponse> {
|
||||
val link = "$mainUrl/?do=search&subaction=search&story=$query"
|
||||
val soup = app.post(link).document
|
||||
|
||||
|
@ -49,7 +49,7 @@ class FrenchStreamProvider : MainAPI() {
|
|||
})
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val soup = app.get(url).document
|
||||
|
||||
val title = soup.selectFirst("h1#s-title").text().toString()
|
||||
|
@ -136,7 +136,7 @@ class FrenchStreamProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
@ -228,7 +228,7 @@ class FrenchStreamProvider : MainAPI() {
|
|||
}
|
||||
|
||||
|
||||
override fun getMainPage(): HomePageResponse? {
|
||||
override suspend fun getMainPage(): HomePageResponse? {
|
||||
val document = app.get(mainUrl).document
|
||||
val docs = document.select("div.sect")
|
||||
val returnList = docs.mapNotNull {
|
||||
|
|
|
@ -13,7 +13,6 @@ import org.jsoup.Jsoup
|
|||
import org.jsoup.nodes.Document
|
||||
import java.io.File
|
||||
import java.net.URI
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
|
||||
|
@ -156,13 +155,13 @@ fun getHeaders(
|
|||
|
||||
fun postRequestCreator(
|
||||
url: String,
|
||||
headers: Map<String, String>,
|
||||
referer: String?,
|
||||
params: Map<String, String>,
|
||||
cookies: Map<String, String>,
|
||||
data: Map<String, String>,
|
||||
cacheTime: Int,
|
||||
cacheUnit: TimeUnit
|
||||
headers: Map<String, String> = emptyMap(),
|
||||
referer: String? = null,
|
||||
params: Map<String, String> = emptyMap(),
|
||||
cookies: Map<String, String> = emptyMap(),
|
||||
data: Map<String, String> = emptyMap(),
|
||||
cacheTime: Int = DEFAULT_TIME,
|
||||
cacheUnit: TimeUnit = DEFAULT_TIME_UNIT
|
||||
): Request {
|
||||
return Request.Builder()
|
||||
.url(addParamsToUrl(url, params))
|
||||
|
@ -174,12 +173,12 @@ fun postRequestCreator(
|
|||
|
||||
fun getRequestCreator(
|
||||
url: String,
|
||||
headers: Map<String, String>,
|
||||
referer: String?,
|
||||
params: Map<String, String>,
|
||||
cookies: Map<String, String>,
|
||||
cacheTime: Int,
|
||||
cacheUnit: TimeUnit
|
||||
headers: Map<String, String> = emptyMap(),
|
||||
referer: String? = null,
|
||||
params: Map<String, String> = emptyMap(),
|
||||
cookies: Map<String, String> = emptyMap(),
|
||||
cacheTime: Int = DEFAULT_TIME,
|
||||
cacheUnit: TimeUnit = DEFAULT_TIME_UNIT
|
||||
): Request {
|
||||
return Request.Builder()
|
||||
.url(addParamsToUrl(url, params))
|
||||
|
@ -213,6 +212,8 @@ open class Requests {
|
|||
val settingsManager = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
val dns = settingsManager.getInt(context.getString(R.string.dns_pref), 0)
|
||||
baseClient = OkHttpClient.Builder()
|
||||
.followRedirects(true)
|
||||
.followSslRedirects(true)
|
||||
.cache(
|
||||
// Note that you need to add a ResponseInterceptor to make this 100% active.
|
||||
// The server response dictates if and when stuff should be cached.
|
||||
|
@ -235,10 +236,10 @@ open class Requests {
|
|||
|
||||
fun get(
|
||||
url: String,
|
||||
headers: Map<String, String> = mapOf(),
|
||||
headers: Map<String, String> = emptyMap(),
|
||||
referer: String? = null,
|
||||
params: Map<String, String> = mapOf(),
|
||||
cookies: Map<String, String> = mapOf(),
|
||||
params: Map<String, String> = emptyMap(),
|
||||
cookies: Map<String, String> = emptyMap(),
|
||||
allowRedirects: Boolean = true,
|
||||
cacheTime: Int = DEFAULT_TIME,
|
||||
cacheUnit: TimeUnit = DEFAULT_TIME_UNIT,
|
||||
|
@ -258,6 +259,10 @@ open class Requests {
|
|||
return AppResponse(response)
|
||||
}
|
||||
|
||||
fun executeRequest(request : Request): AppResponse {
|
||||
return AppResponse(baseClient.newCall(request).execute())
|
||||
}
|
||||
|
||||
fun post(
|
||||
url: String,
|
||||
headers: Map<String, String> = mapOf(),
|
||||
|
|
|
@ -8,14 +8,12 @@ import com.lagradost.cloudstream3.USER_AGENT
|
|||
import com.lagradost.cloudstream3.app
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import java.net.URI
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
/**
|
||||
* When used as Interceptor additionalUrls cannot be returned, use WebViewResolver(...).resolveUsingWebView(...)
|
||||
|
@ -96,7 +94,34 @@ class WebViewResolver(val interceptUrl: Regex, val additionalUrls: List<Regex> =
|
|||
// Suppress image requests as we don't display them anywhere
|
||||
// Less data, low chance of causing issues.
|
||||
// blockNetworkImage also does this job but i will keep it for the future.
|
||||
val blacklistedFiles = listOf(".jpg", ".png", ".webp", ".jpeg", ".webm", ".mp4")
|
||||
val blacklistedFiles = listOf(
|
||||
".jpg",
|
||||
".png",
|
||||
".webp",
|
||||
".mpg",
|
||||
".mpeg",
|
||||
".jpeg",
|
||||
".webm",
|
||||
".mp4",
|
||||
".mp3",
|
||||
".gifv",
|
||||
".flv",
|
||||
".asf",
|
||||
".mov",
|
||||
".mng",
|
||||
".mkv",
|
||||
".ogg",
|
||||
".avi",
|
||||
".wav",
|
||||
".woff2",
|
||||
".woff",
|
||||
".ttf",
|
||||
".css",
|
||||
".vtt",
|
||||
".srt",
|
||||
".ts",
|
||||
".gif",
|
||||
)
|
||||
|
||||
/** NOTE! request.requestHeaders is not perfect!
|
||||
* They don't contain all the headers the browser actually gives.
|
||||
|
@ -105,7 +130,7 @@ class WebViewResolver(val interceptUrl: Regex, val additionalUrls: List<Regex> =
|
|||
* **/
|
||||
return try {
|
||||
when {
|
||||
blacklistedFiles.any { URI(webViewUrl).path.endsWith(it) } || webViewUrl.endsWith(
|
||||
blacklistedFiles.any { URI(webViewUrl).path.contains(it) } || webViewUrl.endsWith(
|
||||
"/favicon.ico"
|
||||
) -> WebResourceResponse(
|
||||
"image/png",
|
||||
|
|
|
@ -14,7 +14,7 @@ class NyaaProvider : MainAPI() {
|
|||
override val vpnStatus = VPNStatus.Torrent
|
||||
override val instantLinkLoading = true
|
||||
|
||||
override fun search(query: String): List<SearchResponse> {
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val url = "$mainUrl/?f=0&c=0_0&q=$query&s=seeders&o=desc"
|
||||
val response = app.get(url).text
|
||||
val document = Jsoup.parse(response)
|
||||
|
@ -35,7 +35,7 @@ class NyaaProvider : MainAPI() {
|
|||
return returnValues
|
||||
}
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val response = app.get(url).text
|
||||
val document = Jsoup.parse(response)
|
||||
val title = document.selectFirst("h3.panel-title").text()
|
||||
|
@ -47,7 +47,7 @@ class NyaaProvider : MainAPI() {
|
|||
return TorrentLoadResponse(title, url, this.name, magnet, fixUrl(torrent), description)
|
||||
}
|
||||
|
||||
override fun loadLinks(
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -2,7 +2,7 @@ package com.lagradost.cloudstream3.ui
|
|||
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.mvvm.Resource
|
||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
|
||||
|
@ -66,15 +66,18 @@ class APIRepository(val api: MainAPI) {
|
|||
}
|
||||
}
|
||||
|
||||
fun loadLinks(
|
||||
suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
if (isInvalidData(data)) return false // this makes providers cleaner
|
||||
|
||||
return normalSafeApiCall { api.loadLinks(data, isCasting, subtitleCallback, callback) }
|
||||
?: false
|
||||
return try {
|
||||
api.loadLinks(data, isCasting, subtitleCallback, callback)
|
||||
} catch (throwable: Throwable) {
|
||||
logError(throwable)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,7 +22,8 @@ import com.google.android.gms.cast.framework.media.RemoteMediaClient
|
|||
import com.google.android.gms.cast.framework.media.uicontroller.UIController
|
||||
import com.google.android.gms.cast.framework.media.widget.ExpandedControllerActivity
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||
import com.lagradost.cloudstream3.mvvm.Resource
|
||||
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
||||
import com.lagradost.cloudstream3.sortSubs
|
||||
import com.lagradost.cloudstream3.sortUrls
|
||||
import com.lagradost.cloudstream3.ui.player.RepoLinkGenerator
|
||||
|
@ -31,11 +32,11 @@ import com.lagradost.cloudstream3.ui.result.ResultEpisode
|
|||
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
||||
import com.lagradost.cloudstream3.utils.CastHelper.awaitLinks
|
||||
import com.lagradost.cloudstream3.utils.CastHelper.getMediaInfo
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||
import com.lagradost.cloudstream3.utils.DataStore.toKotlinObject
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
|
||||
import org.json.JSONObject
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
/*class SkipOpController(val view: ImageView) : UIController() {
|
||||
init {
|
||||
|
@ -265,7 +266,7 @@ class SelectSourceController(val view: ImageView, val activity: ControllerActivi
|
|||
|
||||
if (itemCount != null && itemCount - currentIdIndex == 1 && !isLoadingMore) {
|
||||
isLoadingMore = true
|
||||
thread {
|
||||
ioSafe {
|
||||
val index = meta.currentEpisodeIndex + 1
|
||||
val epData = meta.episodes[index]
|
||||
val currentLinks = mutableSetOf<ExtractorLink>()
|
||||
|
@ -273,7 +274,7 @@ class SelectSourceController(val view: ImageView, val activity: ControllerActivi
|
|||
|
||||
val generator = RepoLinkGenerator(listOf(epData))
|
||||
|
||||
val isSuccessful = normalSafeApiCall {
|
||||
val isSuccessful = safeApiCall {
|
||||
generator.generateLinks(false, true,
|
||||
{
|
||||
it.first?.let { link ->
|
||||
|
@ -286,7 +287,7 @@ class SelectSourceController(val view: ImageView, val activity: ControllerActivi
|
|||
|
||||
val sortedLinks = sortUrls(currentLinks)
|
||||
val sortedSubs = sortSubs(currentSubs)
|
||||
if (isSuccessful == true) {
|
||||
if (isSuccessful == Resource.Success(true)) {
|
||||
if (currentLinks.isNotEmpty()) {
|
||||
val jsonCopy = meta.copy(
|
||||
currentLinks = sortedLinks,
|
||||
|
@ -319,13 +320,10 @@ class SelectSourceController(val view: ImageView, val activity: ControllerActivi
|
|||
}*/
|
||||
activity.runOnUiThread {
|
||||
awaitLinks(
|
||||
|
||||
remoteMediaClient?.queueAppendItem(
|
||||
MediaQueueItem.Builder(mediaInfo).build(),
|
||||
JSONObject()
|
||||
)
|
||||
|
||||
|
||||
) {
|
||||
println("FAILED TO LOAD NEXT ITEM")
|
||||
// loadIndex(1)
|
||||
|
|
|
@ -46,7 +46,7 @@ class DownloadFileGenerator(
|
|||
return episodes[currentIndex]
|
||||
}
|
||||
|
||||
override fun generateLinks(
|
||||
override suspend fun generateLinks(
|
||||
clearCache: Boolean,
|
||||
isCasting: Boolean,
|
||||
callback: (Pair<ExtractorLink?, ExtractorUri?>) -> Unit,
|
||||
|
|
|
@ -16,7 +16,7 @@ interface IGenerator {
|
|||
fun getCurrent(): Any? // this is used to get metadata about the current playing, can return null
|
||||
|
||||
/* not safe, must use try catch */
|
||||
fun generateLinks(
|
||||
suspend fun generateLinks(
|
||||
clearCache: Boolean,
|
||||
isCasting: Boolean,
|
||||
callback: (Pair<ExtractorLink?, ExtractorUri?>) -> Unit,
|
||||
|
|
|
@ -51,7 +51,7 @@ class PlayerGeneratorViewModel : ViewModel() {
|
|||
}
|
||||
|
||||
fun preLoadNextLinks() = viewModelScope.launch {
|
||||
normalSafeApiCall {
|
||||
safeApiCall {
|
||||
if (generator?.hasCache == true && generator?.hasNext() == true) {
|
||||
generator?.next()
|
||||
generator?.generateLinks(clearCache = false, isCasting = false, {}, {})
|
||||
|
@ -97,7 +97,7 @@ class PlayerGeneratorViewModel : ViewModel() {
|
|||
_currentLinks.postValue(currentLinks)
|
||||
}, {
|
||||
currentSubs.add(it)
|
||||
// _currentSubs.postValue(currentSubs) // this causes ConcurrentModificationException, so fuck it
|
||||
// _currentSubs.postValue(currentSubs) // this causes ConcurrentModificationException, so fuck it
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ class PlayerSubtitleHelper {
|
|||
endsWith("vtt", true) -> MimeTypes.TEXT_VTT
|
||||
endsWith("srt", true) -> MimeTypes.APPLICATION_SUBRIP
|
||||
endsWith("xml", true) || endsWith("ttml", true) -> MimeTypes.APPLICATION_TTML
|
||||
else -> MimeTypes.APPLICATION_SUBRIP // TODO get request to see
|
||||
else -> MimeTypes.APPLICATION_SUBRIP
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ class RepoLinkGenerator(private val episodes: List<ResultEpisode>, private var c
|
|||
var linkCache = Array<Set<ExtractorLink>>(size = episodes.size, init = { setOf() })
|
||||
var subsCache = Array<Set<SubtitleData>>(size = episodes.size, init = { setOf() })
|
||||
|
||||
override fun generateLinks(
|
||||
override suspend fun generateLinks(
|
||||
clearCache: Boolean,
|
||||
isCasting: Boolean,
|
||||
callback: (Pair<ExtractorLink?, ExtractorUri?>) -> Unit,
|
||||
|
|
|
@ -98,6 +98,14 @@ object AppUtils {
|
|||
return mapper.readValue(value)
|
||||
}
|
||||
|
||||
inline fun <reified T> tryParseJson(value : String): T? {
|
||||
return try {
|
||||
parseJson(value)
|
||||
} catch (_ : Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
/**| S1:E2 Hello World
|
||||
* | Episode 2. Hello world
|
||||
* | Hello World
|
||||
|
|
Loading…
Reference in a new issue