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 vpnStatus = VPNStatus.None
open val providerType = ProviderType.DirectProvider open val providerType = ProviderType.DirectProvider
open fun getMainPage(): HomePageResponse? { suspend open fun getMainPage(): HomePageResponse? {
throw NotImplementedError() throw NotImplementedError()
} }
open fun search(query: String): List<SearchResponse>? { suspend open fun search(query: String): List<SearchResponse>? {
throw NotImplementedError() throw NotImplementedError()
} }
open fun quickSearch(query: String): List<SearchResponse>? { suspend open fun quickSearch(query: String): List<SearchResponse>? {
throw NotImplementedError() throw NotImplementedError()
} }
open fun load(url: String): LoadResponse? { suspend open fun load(url: String): LoadResponse? {
throw NotImplementedError() throw NotImplementedError()
} }
/**Callback is fired once a link is found, will return true if method is executed successfully*/ /**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, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,

View file

@ -85,7 +85,7 @@ class AllAnimeProvider : MainAPI() {
@JsonProperty("data") val data: Data @JsonProperty("data") val data: Data
) )
override fun search(query: String): ArrayList<SearchResponse> { override suspend fun search(query: String): ArrayList<SearchResponse> {
val link = 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""" """$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 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() val rhino = Context.enter()
rhino.initStandardObjects() rhino.initStandardObjects()
rhino.optimizationLevel = -1 rhino.optimizationLevel = -1
@ -238,7 +238,7 @@ class AllAnimeProvider : MainAPI() {
}) })
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,

View file

@ -27,7 +27,7 @@ class AnimeFlickProvider : MainAPI() {
TvType.ONA 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 link = "https://animeflick.net/search.php?search=$query"
val html = app.get(link).text val html = app.get(link).text
val doc = Jsoup.parse(html) 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 html = app.get(url).text
val doc = Jsoup.parse(html) val doc = Jsoup.parse(html)
@ -79,7 +79,7 @@ class AnimeFlickProvider : MainAPI() {
} }
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,

View file

@ -54,7 +54,7 @@ class AnimePaheProvider : MainAPI() {
TvType.ONA TvType.ONA
) )
override fun getMainPage(): HomePageResponse { override suspend fun getMainPage(): HomePageResponse {
data class Data( data class Data(
@JsonProperty("id") val id: Int, @JsonProperty("id") val id: Int,
@JsonProperty("anime_id") val animeId: 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 url = "$mainUrl/api?m=search&l=8&q=$query"
val headers = mapOf("referer" to "$mainUrl/") 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 { return normalSafeApiCall {
val regex = Regex("""a/(\d+)\?slug=(.+)""") val regex = Regex("""a/(\d+)\?slug=(.+)""")
@ -541,7 +541,7 @@ class AnimePaheProvider : MainAPI() {
return qualities return qualities
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, 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 trendingUrl = "$mainUrl/xz/trending.php?_=$unixTimeMS"
val lastEpisodeUrl = "$mainUrl/xz/epgrid.php?p=1&_=$unixTimeMS" val lastEpisodeUrl = "$mainUrl/xz/epgrid.php?p=1&_=$unixTimeMS"
val recentlyAddedUrl = "$mainUrl/xz/gridgrabrecent.php?p=1&_=$unixTimeMS" val recentlyAddedUrl = "$mainUrl/xz/gridgrabrecent.php?p=1&_=$unixTimeMS"
@ -126,7 +126,7 @@ class DubbedAnimeProvider : MainAPI() {
return href.replace("$mainUrl/", "") 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 url = "$mainUrl/xz/searchgrid.php?p=1&limit=12&s=$query&_=$unixTime"
val response = app.get(url).text val response = app.get(url).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
@ -158,7 +158,7 @@ class DubbedAnimeProvider : MainAPI() {
return returnValue return returnValue
} }
override fun search(query: String): List<SearchResponse> { override suspend fun search(query: String): List<SearchResponse> {
val url = "$mainUrl/search/$query" val url = "$mainUrl/search/$query"
val response = app.get(url).text val response = app.get(url).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
@ -193,7 +193,7 @@ class DubbedAnimeProvider : MainAPI() {
return returnValue return returnValue
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,
@ -230,7 +230,7 @@ class DubbedAnimeProvider : MainAPI() {
return true return true
} }
override fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
if (getIsMovie(url)) { if (getIsMovie(url)) {
val realSlug = url.replace("movies/", "") val realSlug = url.replace("movies/", "")
val episode = getAnimeEpisode(realSlug, true) val episode = getAnimeEpisode(realSlug, true)

View file

@ -37,7 +37,7 @@ class GogoanimeProvider : MainAPI() {
TvType.ONA TvType.ONA
) )
override fun getMainPage(): HomePageResponse { override suspend fun getMainPage(): HomePageResponse {
val headers = mapOf( val headers = mapOf(
"authority" to "ajax.gogo-load.com", "authority" to "ajax.gogo-load.com",
"sec-ch-ua" to "\"Google Chrome\";v=\"89\", \"Chromium\";v=\"89\", \";Not A Brand\";v=\"99\"", "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) 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 link = "$mainUrl/search.html?keyword=$query"
val html = app.get(link).text val html = app.get(link).text
val doc = Jsoup.parse(html) val doc = Jsoup.parse(html)
@ -129,7 +129,7 @@ class GogoanimeProvider : MainAPI() {
return uri return uri
} }
override fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
val link = getProperAnimeLink(url) val link = getProperAnimeLink(url)
val episodeloadApi = "https://ajax.gogo-load.com/ajax/load-list-episode" val episodeloadApi = "https://ajax.gogo-load.com/ajax/load-list-episode"
val html = app.get(link).text val html = app.get(link).text
@ -232,7 +232,7 @@ class GogoanimeProvider : MainAPI() {
} }
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,

View file

@ -14,7 +14,7 @@ class KawaiifuProvider : MainAPI() {
override val supportedTypes = setOf(TvType.Anime, TvType.AnimeMovie, TvType.ONA) override val supportedTypes = setOf(TvType.Anime, TvType.AnimeMovie, TvType.ONA)
override fun getMainPage(): HomePageResponse { override suspend fun getMainPage(): HomePageResponse {
val items = ArrayList<HomePageList>() val items = ArrayList<HomePageList>()
val resp = app.get(mainUrl).text 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 link = "$mainUrl/search-movie?keyword=${query}"
val html = app.get(link).text val html = app.get(link).text
val soup = Jsoup.parse(html) 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 html = app.get(url).text
val soup = Jsoup.parse(html) val soup = Jsoup.parse(html)
@ -110,7 +110,7 @@ class KawaiifuProvider : MainAPI() {
} }
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, 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 items = ArrayList<HomePageList>()
val soup = app.get(mainUrl, interceptor = ddosGuardKiller).document val soup = app.get(mainUrl, interceptor = ddosGuardKiller).document
for (section in soup.select("#content > section")) { for (section in soup.select("#content > section")) {
@ -152,7 +152,7 @@ class TenshiProvider : MainAPI() {
// @JsonProperty("cen") var cen : String // @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) // if (!autoLoadToken()) return quickSearch(query)
// val url = "$mainUrl/anime/search" // val url = "$mainUrl/anime/search"
// val response = khttp.post( // val response = khttp.post(
@ -192,7 +192,7 @@ class TenshiProvider : MainAPI() {
// return returnValue // return returnValue
// } // }
override fun search(query: String): ArrayList<SearchResponse> { override suspend fun search(query: String): ArrayList<SearchResponse> {
val url = "$mainUrl/anime" val url = "$mainUrl/anime"
var document = app.get( var document = app.get(
url, url,
@ -220,7 +220,7 @@ class TenshiProvider : MainAPI() {
return ArrayList(returnValue) return ArrayList(returnValue)
} }
override fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
var document = app.get( var document = app.get(
url, url,
cookies = mapOf("loop-view" to "thumb"), cookies = mapOf("loop-view" to "thumb"),
@ -292,7 +292,7 @@ class TenshiProvider : MainAPI() {
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,

View file

@ -22,7 +22,7 @@ class WatchCartoonOnlineProvider : MainAPI() {
TvType.TvSeries TvType.TvSeries
) )
override fun search(query: String): List<SearchResponse> { override suspend fun search(query: String): List<SearchResponse> {
val url = "https://www.wcostream.com/search" val url = "https://www.wcostream.com/search"
var response = var response =
@ -97,7 +97,7 @@ class WatchCartoonOnlineProvider : MainAPI() {
return returnValue return returnValue
} }
override fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
val isMovie = !url.contains("/anime/") val isMovie = !url.contains("/anime/")
val response = app.get(url).text val response = app.get(url).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
@ -183,7 +183,7 @@ class WatchCartoonOnlineProvider : MainAPI() {
val server: String, val server: String,
) )
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,

View file

@ -29,7 +29,7 @@ class WcoProvider : MainAPI() {
TvType.ONA TvType.ONA
) )
override fun getMainPage(): HomePageResponse { override suspend fun getMainPage(): HomePageResponse {
val urls = listOf( val urls = listOf(
Pair("$mainUrl/ajax/list/recently_updated?type=tv", "Recently Updated Anime"), Pair("$mainUrl/ajax/list/recently_updated?type=tv", "Recently Updated Anime"),
Pair("$mainUrl/ajax/list/recently_updated?type=movie", "Recently Updated Movies"), Pair("$mainUrl/ajax/list/recently_updated?type=movie", "Recently Updated Movies"),
@ -108,7 +108,7 @@ class WcoProvider : MainAPI() {
return returnValue return returnValue
} }
override fun search(query: String): List<SearchResponse> { override suspend fun search(query: String): List<SearchResponse> {
val url = "$mainUrl/search" val url = "$mainUrl/search"
val response = val response =
app.get(url, params = mapOf("keyword" to query)) app.get(url, params = mapOf("keyword" to query))
@ -128,7 +128,7 @@ class WcoProvider : MainAPI() {
return returnValue return returnValue
} }
override fun quickSearch(query: String): List<SearchResponse> { override suspend fun quickSearch(query: String): List<SearchResponse> {
val returnValue: ArrayList<SearchResponse> = ArrayList() val returnValue: ArrayList<SearchResponse> = ArrayList()
val response = JSONObject( val response = JSONObject(
@ -170,7 +170,7 @@ class WcoProvider : MainAPI() {
return returnValue return returnValue
} }
override fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
val response = app.get(url, timeout = 120).text val response = app.get(url, timeout = 120).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
@ -216,7 +216,7 @@ class WcoProvider : MainAPI() {
} }
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, 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 html = app.get("$mainUrl/home").text
val document = Jsoup.parse(html) val document = Jsoup.parse(html)
@ -99,7 +99,7 @@ class ZoroProvider : MainAPI() {
@JsonProperty("html") val html: String @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 url = "$mainUrl/ajax/search/suggest?keyword=${query}"
// val html = mapper.readValue<Response>(khttp.get(url).text).html // val html = mapper.readValue<Response>(khttp.get(url).text).html
// val document = Jsoup.parse(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 link = "$mainUrl/search?keyword=$query"
val html = app.get(link).text val html = app.get(link).text
val document = Jsoup.parse(html) 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 html = app.get(url).text
val document = Jsoup.parse(html) val document = Jsoup.parse(html)
@ -274,7 +274,7 @@ class ZoroProvider : MainAPI() {
@JsonProperty("link") val link: String @JsonProperty("link") val link: String
) )
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, 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 // SAME AS DISCOVER IT SEEMS
// val popularSeries = tmdb.tvService().popular(1, "en-US").execute().body()?.results?.map { // 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. // 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/movie/7445-brothers
// https://www.themoviedb.org/tv/71914-the-wheel-of-time // 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() return tmdb.searchService().multi(query, 1, "en-Us", "US", true).execute()
.body()?.results?.mapNotNull { .body()?.results?.mapNotNull {
it.movie?.toSearchResponse() ?: it.tvShow?.toSearchResponse() 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 // Title, Url
val moviesUrl = listOf( val moviesUrl = listOf(
"Movies" to "$mainUrl/movies", "Movies" to "$mainUrl/movies",
@ -51,7 +51,7 @@ class AkwamProvider : MainAPI() {
return HomePageResponse(pages) 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 url = "$mainUrl/search?q=$query"
val doc = app.get(url).document val doc = app.get(url).document
return doc.select("div.col-lg-auto").mapNotNull { 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 doc = app.get(url).document
val isMovie = url.contains("/movie/") val isMovie = url.contains("/movie/")
val title = doc.select("h1.entry-title").text() val title = doc.select("h1.entry-title").text()
@ -164,7 +164,7 @@ class AkwamProvider : MainAPI() {
} }
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,

View file

@ -28,7 +28,7 @@ class AllMoviesForYouProvider : MainAPI() {
TvType.TvSeries TvType.TvSeries
) )
override fun search(query: String): List<SearchResponse> { override suspend fun search(query: String): List<SearchResponse> {
val url = "$mainUrl/?s=$query" val url = "$mainUrl/?s=$query"
val document = app.get(url).document val document = app.get(url).document
@ -76,7 +76,7 @@ class AllMoviesForYouProvider : MainAPI() {
return if (list.isEmpty()) null else list 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 type = getType(url)
val document = app.get(url).document val document = app.get(url).document
@ -162,7 +162,7 @@ class AllMoviesForYouProvider : MainAPI() {
} }
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, 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 headers = mapOf("X-Requested-By" to "asiaflix-web")
val response = app.get("$apiUrl/dashboard", headers = headers).text val response = app.get("$apiUrl/dashboard", headers = headers).text
@ -138,7 +138,7 @@ class AsiaFlixProvider : MainAPI() {
@JsonProperty("url") val url: String?, @JsonProperty("url") val url: String?,
) )
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,
@ -162,14 +162,14 @@ class AsiaFlixProvider : MainAPI() {
return true 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 headers = mapOf("X-Requested-By" to "asiaflix-web")
val url = "$apiUrl/drama/search?q=$query" val url = "$apiUrl/drama/search?q=$query"
val response = app.get(url, headers = headers).text val response = app.get(url, headers = headers).text
return mapper.readValue<List<Data>?>(response)?.map { it.toSearchResponse() } 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 headers = mapOf("X-Requested-By" to "asiaflix-web")
val requestUrl = "$apiUrl/drama?id=${url.split("/").lastOrNull()}" val requestUrl = "$apiUrl/drama?id=${url.split("/").lastOrNull()}"
val response = app.get(requestUrl, headers = headers).text val response = app.get(requestUrl, headers = headers).text

View file

@ -16,7 +16,7 @@ class DramaSeeProvider : MainAPI() {
override val hasDownloadSupport = true override val hasDownloadSupport = true
override val supportedTypes = setOf(TvType.TvSeries, TvType.Movie) 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 headers = mapOf("X-Requested-By" to "dramasee.net")
val document = app.get(mainUrl, headers = headers).document val document = app.get(mainUrl, headers = headers).document
val mainbody = document.getElementsByTag("body") 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 url = "$mainUrl/search?q=$query"
val html = app.get(url).document val html = app.get(url).document
val document = html.getElementsByTag("body") 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 doc = app.get(url).document
val body = doc.getElementsByTag("body") val body = doc.getElementsByTag("body")
val inner = body?.select("div.series-info") val inner = body?.select("div.series-info")
@ -149,7 +149,7 @@ class DramaSeeProvider : MainAPI() {
) )
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,

View file

@ -18,7 +18,7 @@ class FilmanProvider : MainAPI() {
TvType.TvSeries TvType.TvSeries
) )
override fun getMainPage(): HomePageResponse { override suspend fun getMainPage(): HomePageResponse {
val response = app.get(mainUrl).text val response = app.get(mainUrl).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
val lists = document.select(".item-list,.series-list") val lists = document.select(".item-list,.series-list")
@ -54,7 +54,7 @@ class FilmanProvider : MainAPI() {
return HomePageResponse(categories) 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 url = "$mainUrl/wyszukiwarka?phrase=$query"
val response = app.get(url).text val response = app.get(url).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
@ -79,7 +79,7 @@ class FilmanProvider : MainAPI() {
return getVideos(TvType.Movie, movies) + getVideos(TvType.TvSeries, series) 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 response = app.get(url).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
var title = document.select("span[itemprop=title]").text() 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) return TvSeriesLoadResponse(title, url, name, TvType.TvSeries, episodes, posterUrl, year, plot)
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,

View file

@ -14,7 +14,7 @@ class HDMProvider : MainAPI() {
TvType.Movie, TvType.Movie,
) )
override fun search(query: String): List<SearchResponse> { override suspend fun search(query: String): List<SearchResponse> {
val url = "$mainUrl/search/$query" val url = "$mainUrl/search/$query"
val response = app.get(url).text val response = app.get(url).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
@ -32,7 +32,7 @@ class HDMProvider : MainAPI() {
return returnValue return returnValue
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,
@ -55,7 +55,7 @@ class HDMProvider : MainAPI() {
return true return true
} }
override fun load(url: String): LoadResponse? { override suspend fun load(url: String): LoadResponse? {
val response = app.get(url).text val response = app.get(url).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
val title = document.selectFirst("h2.movieTitle")?.text() ?: throw ErrorLoadingException("No Data Found") 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 html = app.get("$mainUrl", timeout = 25).text
val document = Jsoup.parse(html) val document = Jsoup.parse(html)
val all = ArrayList<HomePageList>() val all = ArrayList<HomePageList>()

View file

@ -14,7 +14,7 @@ class IHaveNoTvProvider : MainAPI() {
override val supportedTypes = setOf(TvType.Documentary) 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", // Uhh, I am too lazy to scrape the "latest documentaries" and "recommended documentaries",
// so I am just scraping 3 random categories // so I am just scraping 3 random categories
val allCategories = listOf( val allCategories = listOf(
@ -67,7 +67,7 @@ class IHaveNoTvProvider : MainAPI() {
return HomePageResponse(items) 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 url = """$mainUrl/search/${URLEncoder.encode(query, "UTF-8")}"""
val response = app.get(url).text val response = app.get(url).text
val soup = Jsoup.parse(response) val soup = Jsoup.parse(response)
@ -101,7 +101,7 @@ class IHaveNoTvProvider : MainAPI() {
return ArrayList(searchResults.values) return ArrayList(searchResults.values)
} }
override fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
val isSeries = url.contains("/series/") val isSeries = url.contains("/series/")
val html = app.get(url).text val html = app.get(url).text
val soup = Jsoup.parse(html) val soup = Jsoup.parse(html)
@ -190,7 +190,7 @@ class IHaveNoTvProvider : MainAPI() {
) else (episodes?.first() as MovieLoadResponse) ) else (episodes?.first() as MovieLoadResponse)
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,

View file

@ -19,7 +19,7 @@ class KdramaHoodProvider : MainAPI() {
override val hasDownloadSupport = true override val hasDownloadSupport = true
override val supportedTypes = setOf(TvType.TvSeries, TvType.Movie) 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 doc = app.get("$mainUrl/home2").document
val home = ArrayList<HomePageList>() val home = ArrayList<HomePageList>()
@ -59,7 +59,7 @@ class KdramaHoodProvider : MainAPI() {
return HomePageResponse(home.filter { it.list.isNotEmpty() }) 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 url = "$mainUrl/?s=$query"
val html = app.get(url).document val html = app.get(url).document
val document = html.getElementsByTag("body") 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 doc = app.get(url).document
val inner = doc.selectFirst("div.central") val inner = doc.selectFirst("div.central")
@ -180,7 +180,7 @@ class KdramaHoodProvider : MainAPI() {
) )
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,

View file

@ -64,7 +64,7 @@ class LookMovieProvider : MainAPI() {
@JsonProperty("season") var season: String, @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 movieUrl = "$mainUrl/api/v1/movies/search/?q=$query"
val movieResponse = app.get(movieUrl).text val movieResponse = app.get(movieUrl).text
val movies = mapper.readValue<LookMovieSearchResultRoot>(movieResponse).result val movies = mapper.readValue<LookMovieSearchResultRoot>(movieResponse).result
@ -109,7 +109,7 @@ class LookMovieProvider : MainAPI() {
return returnValue 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> { fun search(query: String, isMovie: Boolean): ArrayList<SearchResponse> {
val url = "$mainUrl/${if (isMovie) "movies" else "shows"}/search/?q=$query" val url = "$mainUrl/${if (isMovie) "movies" else "shows"}/search/?q=$query"
val response = app.get(url).text val response = app.get(url).text
@ -174,7 +174,7 @@ class LookMovieProvider : MainAPI() {
} }
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,
@ -198,7 +198,7 @@ class LookMovieProvider : MainAPI() {
return true return true
} }
override fun load(url: String): LoadResponse? { override suspend fun load(url: String): LoadResponse? {
val response = app.get(url).text val response = app.get(url).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
val isMovie = url.contains("/movies/") val isMovie = url.contains("/movies/")

View file

@ -28,11 +28,11 @@ class MeloMovieProvider : MainAPI() {
data class MeloMovieLink(val name: String, val link: String) 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) 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 url = "$mainUrl/movie/search/?name=$query"
val returnValue: ArrayList<SearchResponse> = ArrayList() val returnValue: ArrayList<SearchResponse> = ArrayList()
val response = app.get(url).text val response = app.get(url).text
@ -98,7 +98,7 @@ class MeloMovieProvider : MainAPI() {
return parsed.toJson() return parsed.toJson()
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,
@ -111,7 +111,7 @@ class MeloMovieProvider : MainAPI() {
return true return true
} }
override fun load(url: String): LoadResponse? { override suspend fun load(url: String): LoadResponse? {
val response = app.get(url).text val response = app.get(url).text
//backdrop = imgurl //backdrop = imgurl

View file

@ -19,7 +19,7 @@ class PelisplusHDProvider:MainAPI() {
TvType.TvSeries, TvType.TvSeries,
TvType.Anime, TvType.Anime,
) )
override fun getMainPage(): HomePageResponse { override suspend fun getMainPage(): HomePageResponse {
val items = ArrayList<HomePageList>() val items = ArrayList<HomePageList>()
val urls = listOf( val urls = listOf(
Pair("$mainUrl/peliculas", "Peliculas"), Pair("$mainUrl/peliculas", "Peliculas"),
@ -55,7 +55,7 @@ class PelisplusHDProvider:MainAPI() {
return HomePageResponse(items) 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 url = "https://pelisplushd.net/search?s=${query}"
val html = app.get(url).text val html = app.get(url).text
val document = Jsoup.parse(html) 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 html = app.get(url).text
val soup = Jsoup.parse(html) val soup = Jsoup.parse(html)
@ -146,7 +146,7 @@ class PelisplusHDProvider:MainAPI() {
else -> null else -> null
} }
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, 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 // 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. // 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: // 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. // https://vidembed.cc/search.html?keyword=neverland where neverland is the query, can be written as below.
val link = "$mainUrl/search.html?keyword=$query" 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. // 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. // 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. // Gets the url returned from searching.
val html = app.get(url).text val html = app.get(url).text
val soup = Jsoup.parse(html) 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. // 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. // 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 urls = homePageUrlList
val homePageList = ArrayList<HomePageList>() val homePageList = ArrayList<HomePageList>()
// .pmap {} is used to fetch the different pages in parallel // .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() // loadLinks gets the raw .mp4 or .m3u8 urls from the data parameter in the episodes class generated in load()
// See TvSeriesEpisode(...) in this provider. // See TvSeriesEpisode(...) in this provider.
// The data are usually links, but can be any other string to help aid loading the links. // 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, data: String,
isCasting: Boolean, isCasting: Boolean,
// These callbacks are functions you should call when you get a link to a subtitle file or media file. // 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 val hasQuickSearch = false
override fun getMainPage(): HomePageResponse { override suspend fun getMainPage(): HomePageResponse {
val all = ArrayList<HomePageList>() val all = ArrayList<HomePageList>()
val document = app.get(mainUrl, referer = mainUrl).document val document = app.get(mainUrl, referer = mainUrl).document
val mainbody = document.getElementsByTag("body") val mainbody = document.getElementsByTag("body")
@ -65,7 +65,7 @@ class PinoyHDXyzProvider : MainAPI() {
return HomePageResponse(all) 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 url = "$mainUrl/search/?q=${query.replace(" ", "+")}"
val document = app.get(url).document.select("div.portfolio-thumb") val document = app.get(url).document.select("div.portfolio-thumb")
return document?.mapNotNull { return document?.mapNotNull {
@ -88,7 +88,7 @@ class PinoyHDXyzProvider : MainAPI() {
}?.distinctBy { c -> c.url } ?: listOf() }?.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 doc = app.get(url).document
val body = doc.getElementsByTag("body") val body = doc.getElementsByTag("body")
val inner = body?.select("div.info") 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) return MovieLoadResponse(title, url, this.name, tvtype, streamLinks, poster, year, descript, null, null)
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,

View file

@ -16,7 +16,7 @@ class PinoyMoviePediaProvider : MainAPI() {
override val hasMainPage = true override val hasMainPage = true
override val hasQuickSearch = false override val hasQuickSearch = false
override fun getMainPage(): HomePageResponse { override suspend fun getMainPage(): HomePageResponse {
val all = ArrayList<HomePageList>() val all = ArrayList<HomePageList>()
val document = app.get(mainUrl).document val document = app.get(mainUrl).document
val mainbody = document.getElementsByTag("body") val mainbody = document.getElementsByTag("body")
@ -72,7 +72,7 @@ class PinoyMoviePediaProvider : MainAPI() {
return HomePageResponse(all.filter { a -> a.list.isNotEmpty() }) 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 url = "$mainUrl/?s=${query}"
val document = app.get(url).document.selectFirst("div.search-page") val document = app.get(url).document.selectFirst("div.search-page")
?.select("div.result-item") ?.select("div.result-item")
@ -97,7 +97,7 @@ class PinoyMoviePediaProvider : MainAPI() {
}?.distinctBy { c -> c.url } ?: listOf() }?.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 doc = app.get(url).document
val body = doc.getElementsByTag("body") val body = doc.getElementsByTag("body")
val inner = body?.select("div.sheader") 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) return MovieLoadResponse(title, url, this.name, TvType.Movie, streamlinks, poster, year, descript, null, null)
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,

View file

@ -58,7 +58,7 @@ class PinoyMoviesEsProvider : MainAPI() {
} }
return all return all
} }
override fun getMainPage(): HomePageResponse { override suspend fun getMainPage(): HomePageResponse {
val all = ArrayList<HomePageList>() val all = ArrayList<HomePageList>()
val html = app.get(mainUrl).text val html = app.get(mainUrl).text
val document = Jsoup.parse(html) val document = Jsoup.parse(html)
@ -87,7 +87,7 @@ class PinoyMoviesEsProvider : MainAPI() {
return HomePageResponse(all) return HomePageResponse(all)
} }
override fun search(query: String): List<SearchResponse> { override suspend fun search(query: String): List<SearchResponse> {
val url = "$mainUrl/?s=${query}" val url = "$mainUrl/?s=${query}"
val html = app.get(url, interceptor = DdosGuardKiller(true)).text val html = app.get(url, interceptor = DdosGuardKiller(true)).text
//Log.i(this.name, "Result => (html) ${Jsoup.parse(html).getElementsByTag("body")}") //Log.i(this.name, "Result => (html) ${Jsoup.parse(html).getElementsByTag("body")}")
@ -115,7 +115,7 @@ class PinoyMoviesEsProvider : MainAPI() {
return listOf() return listOf()
} }
override fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
val response = app.get(url).text val response = app.get(url).text
val doc = Jsoup.parse(response) val doc = Jsoup.parse(response)
val body = doc.getElementsByTag("body") 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) return MovieLoadResponse(title, url, this.name, TvType.Movie, streamlinks, poster, year, descript, null, null)
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,

View file

@ -1,9 +1,11 @@
package com.lagradost.cloudstream3.movieproviders package com.lagradost.cloudstream3.movieproviders
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.network.WebViewResolver 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.ExtractorLink
import com.lagradost.cloudstream3.utils.M3u8Helper import com.lagradost.cloudstream3.utils.M3u8Helper
import com.lagradost.cloudstream3.utils.getQualityFromName import com.lagradost.cloudstream3.utils.getQualityFromName
@ -26,35 +28,7 @@ class SflixProvider(providerUrl: String, providerName: String) : MainAPI() {
) )
override val vpnStatus = VPNStatus.None override val vpnStatus = VPNStatus.None
private fun Element.toSearchResult(): SearchResponse { override suspend fun getMainPage(): HomePageResponse {
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 {
val html = app.get("$mainUrl/home").text val html = app.get("$mainUrl/home").text
val document = Jsoup.parse(html) val document = Jsoup.parse(html)
@ -84,7 +58,7 @@ class SflixProvider(providerUrl: String, providerName: String) : MainAPI() {
return HomePageResponse(all) 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 url = "$mainUrl/search/${query.replace(" ", "-")}"
val html = app.get(url).text val html = app.get(url).text
val document = Jsoup.parse(html) 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 document = app.get(url).document
val details = document.select("div.detail_page-watch") 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 val episodes = app.get(episodesUrl).text
// Supported streams, they're identical // Supported streams, they're identical
val sourceId = Jsoup.parse(episodes).select("a").firstOrNull { val sourceIds = Jsoup.parse(episodes).select("a").mapNotNull { element ->
it.select("span").text().trim().equals("RapidStream", ignoreCase = true) val sourceId = element.attr("data-id") ?: return@mapNotNull null
|| it.select("span").text().trim().equals("Vidcloud", ignoreCase = true) if(element.select("span")?.text()?.trim()?.isValidServer() == true) {
}?.attr("data-id") "$url.$sourceId".replace("/movie/", "/watch-movie/")
} else {
null
}
}
val webViewUrl = return newMovieLoadResponse(title, url, TvType.Movie, sourceIds.toJson()) {
"$url${sourceId?.let { ".$it" } ?: ""}".replace("/movie/", "/watch-movie/")
return newMovieLoadResponse(title, url, TvType.Movie, webViewUrl) {
this.year = year this.year = year
this.posterUrl = posterUrl this.posterUrl = posterUrl
this.plot = plot this.plot = plot
@ -186,7 +161,8 @@ class SflixProvider(providerUrl: String, providerName: String) : MainAPI() {
episode++ episode++
val episodeNum = 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() Regex("""\d+""").find(str)?.groupValues?.firstOrNull()
?.toIntOrNull() ?.toIntOrNull()
} ?: episode } ?: episode
@ -231,64 +207,102 @@ class SflixProvider(providerUrl: String, providerName: String) : MainAPI() {
@JsonProperty("tracks") val tracks: List<Tracks?>? @JsonProperty("tracks") val tracks: List<Tracks?>?
) )
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
): Boolean { ): Boolean {
val urls = (tryParseJson<Pair<String, String>>(data)?.let { (prefix, server) ->
// To transfer url:::id val episodesUrl = "$mainUrl/ajax/v2/episode/servers/$server"
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 episodes = app.get(episodesUrl).text val episodes = app.get(episodesUrl).text
// Supported streams, they're identical // Supported streams, they're identical
val sourceId = Jsoup.parse(episodes).select("a").firstOrNull { Jsoup.parse(episodes).select("a").mapNotNull { element ->
it.select("span").text().trim().equals("RapidStream", ignoreCase = true) val id = element?.attr("data-id") ?: return@mapNotNull null
|| it.select("span").text().trim().equals("Vidcloud", ignoreCase = true) if(element.select("span")?.text()?.trim()?.isValidServer() == true) {
}?.attr("data-id") "$prefix.$id".replace("/tv/", "/watch-tv/")
} else {
null
}
}
} ?: tryParseJson<List<String>>(data))?.distinct()
"${split[0]}${sourceId?.let { ".$it" } ?: ""}".replace("/tv/", "/watch-tv/") urls?.pmap { url ->
} else { println("FETCHING URL $url")
data 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( return !urls.isNullOrEmpty()
url, }
interceptor = WebViewResolver(
Regex("""/getSources""") 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 { 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>? { fun Sources.toExtractorLink(caller: MainAPI, name: String): List<ExtractorLink>? {
return this.file?.let { file -> return this.file?.let { file ->
//println("FILE::: $file")
val isM3u8 = URI(this.file).path.endsWith(".m3u8") || this.type.equals( val isM3u8 = URI(this.file).path.endsWith(".m3u8") || this.type.equals(
"hls", "hls",
ignoreCase = true ignoreCase = true
@ -296,6 +310,7 @@ class SflixProvider(providerUrl: String, providerName: String) : MainAPI() {
if (isM3u8) { if (isM3u8) {
M3u8Helper().m3u8Generation(M3u8Helper.M3u8Stream(this.file, null), true) M3u8Helper().m3u8Generation(M3u8Helper.M3u8Stream(this.file, null), true)
.map { stream -> .map { stream ->
//println("stream: ${stream.quality} at ${stream.streamUrl}")
val qualityString = if ((stream.quality ?: 0) == 0) label val qualityString = if ((stream.quality ?: 0) == 0) label
?: "" else "${stream.quality}p" ?: "" else "${stream.quality}p"
ExtractorLink( ExtractorLink(

View file

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

View file

@ -13,7 +13,7 @@ class VMoveeProvider : MainAPI() {
override val supportedTypes = setOf(TvType.Movie) 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 url = "$mainUrl/?s=$query"
val response = app.get(url).text val response = app.get(url).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
@ -60,7 +60,7 @@ class VMoveeProvider : MainAPI() {
val data: List<ReeoovAPIData>, val data: List<ReeoovAPIData>,
) )
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,
@ -108,7 +108,7 @@ class VMoveeProvider : MainAPI() {
return true return true
} }
override fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
val response = app.get(url).text val response = app.get(url).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)

View file

@ -16,7 +16,7 @@ class VfFilmProvider : MainAPI() {
override val supportedTypes = setOf(TvType.Movie) 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 url = "$mainUrl/?s=$query"
val response = app.get(url).text val response = app.get(url).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
@ -39,7 +39,7 @@ class VfFilmProvider : MainAPI() {
return returnValue return returnValue
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,
@ -70,7 +70,7 @@ class VfFilmProvider : MainAPI() {
return vudoUrl return vudoUrl
} }
override fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
val response = app.get(url).text val response = app.get(url).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
val title = document?.selectFirst("div.SubTitle")?.text() val title = document?.selectFirst("div.SubTitle")?.text()

View file

@ -17,7 +17,7 @@ class VfSerieProvider : MainAPI() {
override val supportedTypes = setOf(TvType.TvSeries) 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 url = "$mainUrl/?s=$query"
val response = app.get(url).text val response = app.get(url).text
val document = Jsoup.parse(response) 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 .toString() // direct mp4 link, https://m5.vudeo.net/2vp3xgpw2avjdohilpfbtyuxzzrqzuh4z5yxvztral5k3rjnba6f4byj3saa/v.mp4 for exemple
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,
@ -95,7 +95,7 @@ class VfSerieProvider : MainAPI() {
return true return true
} }
override fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
val response = app.get(url).text val response = app.get(url).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
val title = 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 // 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. // 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: // 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. // https://vidembed.cc/search.html?keyword=neverland where neverland is the query, can be written as below.
val link = "$mainUrl/search.html?keyword=$query" 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. // 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. // 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. // Gets the url returned from searching.
val html = app.get(url).text val html = app.get(url).text
val soup = Jsoup.parse(html) 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. // 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. // 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 urls = homePageUrlList
val homePageList = ArrayList<HomePageList>() val homePageList = ArrayList<HomePageList>()
// .pmap {} is used to fetch the different pages in parallel // .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() // loadLinks gets the raw .mp4 or .m3u8 urls from the data parameter in the episodes class generated in load()
// See TvSeriesEpisode(...) in this provider. // See TvSeriesEpisode(...) in this provider.
// The data are usually links, but can be any other string to help aid loading the links. // 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, data: String,
isCasting: Boolean, isCasting: Boolean,
// These callbacks are functions you should call when you get a link to a subtitle file or media file. // 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 hasDownloadSupport = true
override val supportedTypes = setOf(TvType.TvSeries, TvType.Movie) 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 headers = mapOf("X-Requested-By" to mainUrl)
val doc = app.get(mainUrl, headers = headers).document val doc = app.get(mainUrl, headers = headers).document
val rowPair = mutableListOf<Pair<String, String>>() 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 url = "$mainUrl/search?type=movies&keyword=$query"
val document = app.get(url).document.getElementsByTag("body") val document = app.get(url).document.getElementsByTag("body")
.select("div.block.tab-container > div > ul > li") ?: return listOf() .select("div.block.tab-container > div > ul > li") ?: return listOf()
@ -89,7 +89,7 @@ class WatchAsianProvider : MainAPI() {
}.distinctBy { a -> a.url } }.distinctBy { a -> a.url }
} }
override fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
val body = app.get(url).document val body = app.get(url).document
// Declare vars // Declare vars
val isDramaDetail = url.contains("/drama-detail/") val isDramaDetail = url.contains("/drama-detail/")
@ -163,7 +163,7 @@ class WatchAsianProvider : MainAPI() {
) )
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,

View file

@ -13,7 +13,7 @@ class FrenchStreamProvider : MainAPI() {
override val lang = "fr" override val lang = "fr"
override val supportedTypes = setOf(TvType.AnimeMovie, TvType.TvSeries, TvType.Movie) 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 link = "$mainUrl/?do=search&subaction=search&story=$query"
val soup = app.post(link).document 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 soup = app.get(url).document
val title = soup.selectFirst("h1#s-title").text().toString() 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, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, 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 document = app.get(mainUrl).document
val docs = document.select("div.sect") val docs = document.select("div.sect")
val returnList = docs.mapNotNull { val returnList = docs.mapNotNull {

View file

@ -13,7 +13,6 @@ import org.jsoup.Jsoup
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import java.io.File import java.io.File
import java.net.URI import java.net.URI
import java.util.*
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -156,13 +155,13 @@ fun getHeaders(
fun postRequestCreator( fun postRequestCreator(
url: String, url: String,
headers: Map<String, String>, headers: Map<String, String> = emptyMap(),
referer: String?, referer: String? = null,
params: Map<String, String>, params: Map<String, String> = emptyMap(),
cookies: Map<String, String>, cookies: Map<String, String> = emptyMap(),
data: Map<String, String>, data: Map<String, String> = emptyMap(),
cacheTime: Int, cacheTime: Int = DEFAULT_TIME,
cacheUnit: TimeUnit cacheUnit: TimeUnit = DEFAULT_TIME_UNIT
): Request { ): Request {
return Request.Builder() return Request.Builder()
.url(addParamsToUrl(url, params)) .url(addParamsToUrl(url, params))
@ -174,12 +173,12 @@ fun postRequestCreator(
fun getRequestCreator( fun getRequestCreator(
url: String, url: String,
headers: Map<String, String>, headers: Map<String, String> = emptyMap(),
referer: String?, referer: String? = null,
params: Map<String, String>, params: Map<String, String> = emptyMap(),
cookies: Map<String, String>, cookies: Map<String, String> = emptyMap(),
cacheTime: Int, cacheTime: Int = DEFAULT_TIME,
cacheUnit: TimeUnit cacheUnit: TimeUnit = DEFAULT_TIME_UNIT
): Request { ): Request {
return Request.Builder() return Request.Builder()
.url(addParamsToUrl(url, params)) .url(addParamsToUrl(url, params))
@ -213,6 +212,8 @@ open class Requests {
val settingsManager = PreferenceManager.getDefaultSharedPreferences(context) val settingsManager = PreferenceManager.getDefaultSharedPreferences(context)
val dns = settingsManager.getInt(context.getString(R.string.dns_pref), 0) val dns = settingsManager.getInt(context.getString(R.string.dns_pref), 0)
baseClient = OkHttpClient.Builder() baseClient = OkHttpClient.Builder()
.followRedirects(true)
.followSslRedirects(true)
.cache( .cache(
// Note that you need to add a ResponseInterceptor to make this 100% active. // Note that you need to add a ResponseInterceptor to make this 100% active.
// The server response dictates if and when stuff should be cached. // The server response dictates if and when stuff should be cached.
@ -235,10 +236,10 @@ open class Requests {
fun get( fun get(
url: String, url: String,
headers: Map<String, String> = mapOf(), headers: Map<String, String> = emptyMap(),
referer: String? = null, referer: String? = null,
params: Map<String, String> = mapOf(), params: Map<String, String> = emptyMap(),
cookies: Map<String, String> = mapOf(), cookies: Map<String, String> = emptyMap(),
allowRedirects: Boolean = true, allowRedirects: Boolean = true,
cacheTime: Int = DEFAULT_TIME, cacheTime: Int = DEFAULT_TIME,
cacheUnit: TimeUnit = DEFAULT_TIME_UNIT, cacheUnit: TimeUnit = DEFAULT_TIME_UNIT,
@ -258,6 +259,10 @@ open class Requests {
return AppResponse(response) return AppResponse(response)
} }
fun executeRequest(request : Request): AppResponse {
return AppResponse(baseClient.newCall(request).execute())
}
fun post( fun post(
url: String, url: String,
headers: Map<String, String> = mapOf(), 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.app
import com.lagradost.cloudstream3.utils.Coroutines.main import com.lagradost.cloudstream3.utils.Coroutines.main
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import okhttp3.Interceptor import okhttp3.Interceptor
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import java.net.URI import java.net.URI
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlin.concurrent.thread
/** /**
* When used as Interceptor additionalUrls cannot be returned, use WebViewResolver(...).resolveUsingWebView(...) * 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 // Suppress image requests as we don't display them anywhere
// Less data, low chance of causing issues. // Less data, low chance of causing issues.
// blockNetworkImage also does this job but i will keep it for the future. // 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! /** NOTE! request.requestHeaders is not perfect!
* They don't contain all the headers the browser actually gives. * 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 { return try {
when { when {
blacklistedFiles.any { URI(webViewUrl).path.endsWith(it) } || webViewUrl.endsWith( blacklistedFiles.any { URI(webViewUrl).path.contains(it) } || webViewUrl.endsWith(
"/favicon.ico" "/favicon.ico"
) -> WebResourceResponse( ) -> WebResourceResponse(
"image/png", "image/png",

View file

@ -14,7 +14,7 @@ class NyaaProvider : MainAPI() {
override val vpnStatus = VPNStatus.Torrent override val vpnStatus = VPNStatus.Torrent
override val instantLinkLoading = true 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 url = "$mainUrl/?f=0&c=0_0&q=$query&s=seeders&o=desc"
val response = app.get(url).text val response = app.get(url).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
@ -35,7 +35,7 @@ class NyaaProvider : MainAPI() {
return returnValues return returnValues
} }
override fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
val response = app.get(url).text val response = app.get(url).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
val title = document.selectFirst("h3.panel-title").text() 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) return TorrentLoadResponse(title, url, this.name, magnet, fixUrl(torrent), description)
} }
override fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,

View file

@ -2,7 +2,7 @@ package com.lagradost.cloudstream3.ui
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.mvvm.Resource 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.mvvm.safeApiCall
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
@ -66,15 +66,18 @@ class APIRepository(val api: MainAPI) {
} }
} }
fun loadLinks( suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
): Boolean { ): Boolean {
if (isInvalidData(data)) return false // this makes providers cleaner if (isInvalidData(data)) return false // this makes providers cleaner
return try {
return normalSafeApiCall { api.loadLinks(data, isCasting, subtitleCallback, callback) } api.loadLinks(data, isCasting, subtitleCallback, callback)
?: false } 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.uicontroller.UIController
import com.google.android.gms.cast.framework.media.widget.ExpandedControllerActivity import com.google.android.gms.cast.framework.media.widget.ExpandedControllerActivity
import com.lagradost.cloudstream3.R 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.sortSubs
import com.lagradost.cloudstream3.sortUrls import com.lagradost.cloudstream3.sortUrls
import com.lagradost.cloudstream3.ui.player.RepoLinkGenerator 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.AppUtils.toJson
import com.lagradost.cloudstream3.utils.CastHelper.awaitLinks import com.lagradost.cloudstream3.utils.CastHelper.awaitLinks
import com.lagradost.cloudstream3.utils.CastHelper.getMediaInfo 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.DataStore.toKotlinObject
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
import org.json.JSONObject import org.json.JSONObject
import kotlin.concurrent.thread
/*class SkipOpController(val view: ImageView) : UIController() { /*class SkipOpController(val view: ImageView) : UIController() {
init { init {
@ -265,7 +266,7 @@ class SelectSourceController(val view: ImageView, val activity: ControllerActivi
if (itemCount != null && itemCount - currentIdIndex == 1 && !isLoadingMore) { if (itemCount != null && itemCount - currentIdIndex == 1 && !isLoadingMore) {
isLoadingMore = true isLoadingMore = true
thread { ioSafe {
val index = meta.currentEpisodeIndex + 1 val index = meta.currentEpisodeIndex + 1
val epData = meta.episodes[index] val epData = meta.episodes[index]
val currentLinks = mutableSetOf<ExtractorLink>() val currentLinks = mutableSetOf<ExtractorLink>()
@ -273,7 +274,7 @@ class SelectSourceController(val view: ImageView, val activity: ControllerActivi
val generator = RepoLinkGenerator(listOf(epData)) val generator = RepoLinkGenerator(listOf(epData))
val isSuccessful = normalSafeApiCall { val isSuccessful = safeApiCall {
generator.generateLinks(false, true, generator.generateLinks(false, true,
{ {
it.first?.let { link -> it.first?.let { link ->
@ -286,7 +287,7 @@ class SelectSourceController(val view: ImageView, val activity: ControllerActivi
val sortedLinks = sortUrls(currentLinks) val sortedLinks = sortUrls(currentLinks)
val sortedSubs = sortSubs(currentSubs) val sortedSubs = sortSubs(currentSubs)
if (isSuccessful == true) { if (isSuccessful == Resource.Success(true)) {
if (currentLinks.isNotEmpty()) { if (currentLinks.isNotEmpty()) {
val jsonCopy = meta.copy( val jsonCopy = meta.copy(
currentLinks = sortedLinks, currentLinks = sortedLinks,
@ -319,13 +320,10 @@ class SelectSourceController(val view: ImageView, val activity: ControllerActivi
}*/ }*/
activity.runOnUiThread { activity.runOnUiThread {
awaitLinks( awaitLinks(
remoteMediaClient?.queueAppendItem( remoteMediaClient?.queueAppendItem(
MediaQueueItem.Builder(mediaInfo).build(), MediaQueueItem.Builder(mediaInfo).build(),
JSONObject() JSONObject()
) )
) { ) {
println("FAILED TO LOAD NEXT ITEM") println("FAILED TO LOAD NEXT ITEM")
// loadIndex(1) // loadIndex(1)

View file

@ -46,7 +46,7 @@ class DownloadFileGenerator(
return episodes[currentIndex] return episodes[currentIndex]
} }
override fun generateLinks( override suspend fun generateLinks(
clearCache: Boolean, clearCache: Boolean,
isCasting: Boolean, isCasting: Boolean,
callback: (Pair<ExtractorLink?, ExtractorUri?>) -> Unit, 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 fun getCurrent(): Any? // this is used to get metadata about the current playing, can return null
/* not safe, must use try catch */ /* not safe, must use try catch */
fun generateLinks( suspend fun generateLinks(
clearCache: Boolean, clearCache: Boolean,
isCasting: Boolean, isCasting: Boolean,
callback: (Pair<ExtractorLink?, ExtractorUri?>) -> Unit, callback: (Pair<ExtractorLink?, ExtractorUri?>) -> Unit,

View file

@ -51,7 +51,7 @@ class PlayerGeneratorViewModel : ViewModel() {
} }
fun preLoadNextLinks() = viewModelScope.launch { fun preLoadNextLinks() = viewModelScope.launch {
normalSafeApiCall { safeApiCall {
if (generator?.hasCache == true && generator?.hasNext() == true) { if (generator?.hasCache == true && generator?.hasNext() == true) {
generator?.next() generator?.next()
generator?.generateLinks(clearCache = false, isCasting = false, {}, {}) generator?.generateLinks(clearCache = false, isCasting = false, {}, {})
@ -97,7 +97,7 @@ class PlayerGeneratorViewModel : ViewModel() {
_currentLinks.postValue(currentLinks) _currentLinks.postValue(currentLinks)
}, { }, {
currentSubs.add(it) 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("vtt", true) -> MimeTypes.TEXT_VTT
endsWith("srt", true) -> MimeTypes.APPLICATION_SUBRIP endsWith("srt", true) -> MimeTypes.APPLICATION_SUBRIP
endsWith("xml", true) || endsWith("ttml", true) -> MimeTypes.APPLICATION_TTML 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 linkCache = Array<Set<ExtractorLink>>(size = episodes.size, init = { setOf() })
var subsCache = Array<Set<SubtitleData>>(size = episodes.size, init = { setOf() }) var subsCache = Array<Set<SubtitleData>>(size = episodes.size, init = { setOf() })
override fun generateLinks( override suspend fun generateLinks(
clearCache: Boolean, clearCache: Boolean,
isCasting: Boolean, isCasting: Boolean,
callback: (Pair<ExtractorLink?, ExtractorUri?>) -> Unit, callback: (Pair<ExtractorLink?, ExtractorUri?>) -> Unit,

View file

@ -98,6 +98,14 @@ object AppUtils {
return mapper.readValue(value) return mapper.readValue(value)
} }
inline fun <reified T> tryParseJson(value : String): T? {
return try {
parseJson(value)
} catch (_ : Exception) {
null
}
}
/**| S1:E2 Hello World /**| S1:E2 Hello World
* | Episode 2. Hello world * | Episode 2. Hello world
* | Hello World * | Hello World