This commit is contained in:
LagradOst 2022-01-16 23:31:42 +01:00
parent fd6eee635f
commit 44c7d5ff8c
46 changed files with 307 additions and 253 deletions

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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)

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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()

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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>()

View File

@ -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,

View File

@ -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,

View File

@ -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/")

View File

@ -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

View File

@ -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,

View File

@ -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.

View 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,

View File

@ -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,

View File

@ -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,

View File

@ -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(

View File

@ -28,7 +28,7 @@ class TrailersTwoProvider : TmdbProvider() {
TvType.Cartoon
)
override fun loadLinks(
override suspend fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,

View File

@ -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)

View File

@ -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()

View File

@ -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 =

View File

@ -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.

View 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,

View File

@ -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 {

View File

@ -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(),

View File

@ -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",

View File

@ -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,

View File

@ -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
}
}
}

View File

@ -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)

View File

@ -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,

View File

@ -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,

View File

@ -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
})
}

View File

@ -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
}
}

View File

@ -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,

View File

@ -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