forked from recloudstream/cloudstream
api fix + VPN status + 1 frame issue resolved
This commit is contained in:
parent
f02793f62a
commit
08d557a82e
9 changed files with 98 additions and 19 deletions
|
@ -13,7 +13,7 @@ import java.util.*
|
||||||
|
|
||||||
const val USER_AGENT =
|
const val USER_AGENT =
|
||||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
|
||||||
val baseHeader = mapOf("User-Agent" to USER_AGENT)
|
//val baseHeader = mapOf("User-Agent" to USER_AGENT)
|
||||||
val mapper = JsonMapper.builder().addModule(KotlinModule())
|
val mapper = JsonMapper.builder().addModule(KotlinModule())
|
||||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).build()!!
|
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).build()!!
|
||||||
|
|
||||||
|
@ -119,6 +119,8 @@ abstract class MainAPI {
|
||||||
TvType.ONA
|
TvType.ONA
|
||||||
)
|
)
|
||||||
|
|
||||||
|
open val vpnStatus = VPNStatus.None
|
||||||
|
|
||||||
open fun getMainPage(): HomePageResponse? {
|
open fun getMainPage(): HomePageResponse? {
|
||||||
throw NotImplementedError()
|
throw NotImplementedError()
|
||||||
}
|
}
|
||||||
|
@ -197,6 +199,12 @@ fun imdbUrlToIdNullable(url: String?): String? {
|
||||||
return imdbUrlToId(url)
|
return imdbUrlToId(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class VPNStatus {
|
||||||
|
None,
|
||||||
|
MightBeNeeded,
|
||||||
|
Torrent,
|
||||||
|
}
|
||||||
|
|
||||||
enum class ShowStatus {
|
enum class ShowStatus {
|
||||||
Completed,
|
Completed,
|
||||||
Ongoing,
|
Ongoing,
|
||||||
|
|
|
@ -10,6 +10,11 @@ class DoodToExtractor : DoodLaExtractor() {
|
||||||
get() = "https://dood.to"
|
get() = "https://dood.to"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DoodSoExtractor : DoodLaExtractor() {
|
||||||
|
override val mainUrl: String
|
||||||
|
get() = "https://dood.so"
|
||||||
|
}
|
||||||
|
|
||||||
open class DoodLaExtractor : ExtractorApi() {
|
open class DoodLaExtractor : ExtractorApi() {
|
||||||
override val name: String
|
override val name: String
|
||||||
get() = "DoodStream"
|
get() = "DoodStream"
|
||||||
|
@ -33,7 +38,16 @@ open class DoodLaExtractor : ExtractorApi() {
|
||||||
val downloadResponse = khttp.get(downloadLink)
|
val downloadResponse = khttp.get(downloadLink)
|
||||||
Regex("onclick=\"window\\.open\\((['\"])(.*?)(['\"])").find(downloadResponse.text)?.groupValues?.get(2)
|
Regex("onclick=\"window\\.open\\((['\"])(.*?)(['\"])").find(downloadResponse.text)?.groupValues?.get(2)
|
||||||
?.let { trueLink ->
|
?.let { trueLink ->
|
||||||
return listOf(ExtractorLink(trueLink, this.name, trueLink, mainUrl, Qualities.Unknown.value, false)) // links are valid in 8h
|
return listOf(
|
||||||
|
ExtractorLink(
|
||||||
|
trueLink,
|
||||||
|
this.name,
|
||||||
|
trueLink,
|
||||||
|
mainUrl,
|
||||||
|
Qualities.Unknown.value,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
) // links are valid in 8h
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
package com.lagradost.cloudstream3.movieproviders
|
package com.lagradost.cloudstream3.movieproviders
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
|
import com.lagradost.cloudstream3.utils.Qualities
|
||||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
|
import org.jsoup.nodes.Document
|
||||||
|
|
||||||
class AllMoviesForYouProvider : MainAPI() {
|
class AllMoviesForYouProvider : MainAPI() {
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -47,8 +50,21 @@ class AllMoviesForYouProvider : MainAPI() {
|
||||||
return returnValue
|
return returnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getLink(document: String): String? {
|
private fun getLink(document: Document): List<String>? {
|
||||||
return Regex("iframe src=\"(.*?)\"").find(document)?.groupValues?.get(1)
|
val list = ArrayList<String>()
|
||||||
|
Regex("iframe src=\"(.*?)\"").find(document.html())?.groupValues?.get(1)?.let {
|
||||||
|
list.add(it)
|
||||||
|
}
|
||||||
|
document.select("div.OptionBx")?.forEach { element ->
|
||||||
|
val baseElement = element.selectFirst("> a.Button")
|
||||||
|
if (element.selectFirst("> p.AAIco-dns")?.text() == "Streamhub") {
|
||||||
|
baseElement?.attr("href")?.let { href ->
|
||||||
|
list.add(href)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (list.isEmpty()) null else list
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun load(url: String): LoadResponse {
|
override fun load(url: String): LoadResponse {
|
||||||
|
@ -118,7 +134,7 @@ class AllMoviesForYouProvider : MainAPI() {
|
||||||
rating
|
rating
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
val data = getLink(response.text)
|
val data = getLink(document)
|
||||||
?: throw ErrorLoadingException("No Links Found")
|
?: throw ErrorLoadingException("No Links Found")
|
||||||
|
|
||||||
return MovieLoadResponse(
|
return MovieLoadResponse(
|
||||||
|
@ -126,7 +142,7 @@ class AllMoviesForYouProvider : MainAPI() {
|
||||||
url,
|
url,
|
||||||
this.name,
|
this.name,
|
||||||
type,
|
type,
|
||||||
data,
|
mapper.writeValueAsString(data),
|
||||||
backgroundPoster,
|
backgroundPoster,
|
||||||
year?.toIntOrNull(),
|
year?.toIntOrNull(),
|
||||||
descipt,
|
descipt,
|
||||||
|
@ -145,19 +161,31 @@ class AllMoviesForYouProvider : MainAPI() {
|
||||||
): Boolean {
|
): Boolean {
|
||||||
if (data.startsWith("$mainUrl/episode/")) {
|
if (data.startsWith("$mainUrl/episode/")) {
|
||||||
val response = khttp.get(data)
|
val response = khttp.get(data)
|
||||||
val link = getLink(response.text)
|
getLink(Jsoup.parse(response.text))?.let { links ->
|
||||||
if (link == null || link == data) return false
|
for (link in links) {
|
||||||
return loadLinks(link, isCasting, subtitleCallback, callback)
|
if (link == data) continue
|
||||||
}
|
loadLinks(link, isCasting, subtitleCallback, callback)
|
||||||
|
|
||||||
if (data.startsWith(mainUrl) && data != mainUrl) {
|
|
||||||
val response = khttp.get(data.replace("&", "&"))
|
|
||||||
Regex("<iframe.*?src=\"(.*?)\"").find(response.text)?.groupValues?.get(1)?.let { url ->
|
|
||||||
loadExtractor(url.trimStart(), data, callback)
|
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
} else if (data.startsWith(mainUrl) && data != mainUrl) {
|
||||||
|
val realDataUrl = data.replace("&", "&").replace("&", "&")
|
||||||
|
if (data.contains("trdownload")) {
|
||||||
|
callback(ExtractorLink(this.name, this.name, realDataUrl, mainUrl, Qualities.Unknown.value))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
val response = khttp.get(realDataUrl)
|
||||||
|
Regex("<iframe.*?src=\"(.*?)\"").find(response.text)?.groupValues?.get(1)?.let { url ->
|
||||||
|
loadExtractor(url.trimStart(), realDataUrl, callback)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
val links = mapper.readValue<List<String>>(data)
|
||||||
|
for (link in links) {
|
||||||
|
loadLinks(link, isCasting, subtitleCallback, callback)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -29,6 +29,9 @@ class TrailersToProvider : MainAPI() {
|
||||||
TvType.TvSeries,
|
TvType.TvSeries,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
override val vpnStatus: VPNStatus
|
||||||
|
get() = VPNStatus.MightBeNeeded
|
||||||
|
|
||||||
override fun getMainPage(): HomePageResponse? {
|
override fun getMainPage(): HomePageResponse? {
|
||||||
val response = khttp.get(mainUrl)
|
val response = khttp.get(mainUrl)
|
||||||
val document = Jsoup.parse(response.text)
|
val document = Jsoup.parse(response.text)
|
||||||
|
|
|
@ -143,7 +143,7 @@ fun ResultEpisode.getWatchProgress(): Float {
|
||||||
|
|
||||||
class ResultFragment : Fragment() {
|
class ResultFragment : Fragment() {
|
||||||
companion object {
|
companion object {
|
||||||
fun newInstance(url: String, apiName: String, startAction: Int = 0, startValue : Int = 0) =
|
fun newInstance(url: String, apiName: String, startAction: Int = 0, startValue: Int = 0) =
|
||||||
ResultFragment().apply {
|
ResultFragment().apply {
|
||||||
arguments = Bundle().apply {
|
arguments = Bundle().apply {
|
||||||
putString("url", url)
|
putString("url", url)
|
||||||
|
@ -252,6 +252,7 @@ class ResultFragment : Fragment() {
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
activity?.window?.decorView?.clearFocus()
|
activity?.window?.decorView?.clearFocus()
|
||||||
hideKeyboard()
|
hideKeyboard()
|
||||||
|
|
||||||
|
@ -526,6 +527,7 @@ class ResultFragment : Fragment() {
|
||||||
val isLoaded = when (episodeClick.action) {
|
val isLoaded = when (episodeClick.action) {
|
||||||
ACTION_PLAY_EPISODE_IN_PLAYER -> true
|
ACTION_PLAY_EPISODE_IN_PLAYER -> true
|
||||||
ACTION_CLICK_DEFAULT -> true
|
ACTION_CLICK_DEFAULT -> true
|
||||||
|
ACTION_SHOW_TOAST -> true
|
||||||
ACTION_CHROME_CAST_EPISODE -> requireLinks(true)
|
ACTION_CHROME_CAST_EPISODE -> requireLinks(true)
|
||||||
ACTION_CHROME_CAST_MIRROR -> requireLinks(true)
|
ACTION_CHROME_CAST_MIRROR -> requireLinks(true)
|
||||||
else -> requireLinks(false)
|
else -> requireLinks(false)
|
||||||
|
@ -841,6 +843,13 @@ class ResultFragment : Fragment() {
|
||||||
if (d is LoadResponse) {
|
if (d is LoadResponse) {
|
||||||
updateVisStatus(2)
|
updateVisStatus(2)
|
||||||
|
|
||||||
|
result_vpn.text = when (api.vpnStatus) {
|
||||||
|
VPNStatus.MightBeNeeded -> getString(R.string.vpn_might_be_needed)
|
||||||
|
VPNStatus.Torrent -> getString(R.string.vpn_torrent)
|
||||||
|
else -> ""
|
||||||
|
}
|
||||||
|
result_vpn.visibility = if (api.vpnStatus == VPNStatus.None) GONE else VISIBLE
|
||||||
|
|
||||||
result_bookmark_button.text = "Watching"
|
result_bookmark_button.text = "Watching"
|
||||||
|
|
||||||
currentHeaderName = d.name
|
currentHeaderName = d.name
|
||||||
|
|
|
@ -72,8 +72,11 @@ val extractorApis: Array<ExtractorApi> = arrayOf(
|
||||||
XStreamCdn(),
|
XStreamCdn(),
|
||||||
StreamSB(),
|
StreamSB(),
|
||||||
Streamhub(),
|
Streamhub(),
|
||||||
DoodLaExtractor(),
|
|
||||||
|
// dood extractors
|
||||||
DoodToExtractor(),
|
DoodToExtractor(),
|
||||||
|
DoodSoExtractor(),
|
||||||
|
DoodLaExtractor(),
|
||||||
)
|
)
|
||||||
|
|
||||||
fun getExtractorApiFromName(name: String): ExtractorApi {
|
fun getExtractorApiFromName(name: String): ExtractorApi {
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
tools:context=".ui.home.HomeFragment">
|
tools:context=".ui.home.HomeFragment">
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
|
android:visibility="visible"
|
||||||
|
tools:visibility="gone"
|
||||||
android:id="@+id/home_loading"
|
android:id="@+id/home_loading"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
@ -34,6 +36,7 @@
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:visibility="gone"
|
||||||
tools:visibility="gone"
|
tools:visibility="gone"
|
||||||
android:id="@+id/home_loading_error"
|
android:id="@+id/home_loading_error"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
|
@ -71,6 +74,8 @@
|
||||||
/>
|
/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
<androidx.core.widget.NestedScrollView
|
<androidx.core.widget.NestedScrollView
|
||||||
|
tools:visibility="visible"
|
||||||
|
android:visibility="gone"
|
||||||
android:id="@+id/home_loaded"
|
android:id="@+id/home_loaded"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
android:layout_width="50dp" android:layout_height="50dp">
|
android:layout_width="50dp" android:layout_height="50dp">
|
||||||
</ProgressBar>
|
</ProgressBar>
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:visibility="gone"
|
||||||
tools:visibility="gone"
|
tools:visibility="gone"
|
||||||
android:id="@+id/result_loading_error"
|
android:id="@+id/result_loading_error"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
|
@ -265,7 +266,12 @@
|
||||||
</ImageView>
|
</ImageView>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/result_vpn"
|
||||||
|
android:textSize="15sp"
|
||||||
|
tools:text="@string/vpn_torrent"
|
||||||
|
android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||||
|
</TextView>
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
|
@ -95,4 +95,7 @@
|
||||||
|
|
||||||
<string name="action_remove_watching">Remove</string>
|
<string name="action_remove_watching">Remove</string>
|
||||||
<string name="action_open_watching">More Info</string>
|
<string name="action_open_watching">More Info</string>
|
||||||
|
|
||||||
|
<string name="vpn_might_be_needed">A VPN might be needed for this provider to work correctly</string>
|
||||||
|
<string name="vpn_torrent">This providers is a torrent, a VPN is recommended</string>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in a new issue