mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
fixed #461
This commit is contained in:
parent
fd6eee635f
commit
44c7d5ff8c
46 changed files with 307 additions and 253 deletions
|
@ -231,24 +231,24 @@ abstract class MainAPI {
|
||||||
open val vpnStatus = VPNStatus.None
|
open val 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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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>()
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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/")
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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 =
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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)
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue