forked from recloudstream/cloudstream
Added Streamlare extractor
This commit is contained in:
parent
e21518567e
commit
56218529c3
4 changed files with 84 additions and 9 deletions
|
@ -0,0 +1,60 @@
|
||||||
|
package com.lagradost.cloudstream3.extractors
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
|
import com.lagradost.cloudstream3.app
|
||||||
|
import com.lagradost.cloudstream3.utils.ExtractorApi
|
||||||
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
|
import com.lagradost.cloudstream3.utils.Qualities
|
||||||
|
import com.lagradost.nicehttp.RequestBodyTypes
|
||||||
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
|
|
||||||
|
|
||||||
|
class Streamlare : Slmaxed() {
|
||||||
|
override val mainUrl = "https://streamlare.com/"
|
||||||
|
}
|
||||||
|
|
||||||
|
open class Slmaxed : ExtractorApi() {
|
||||||
|
override val name = "Streamlare"
|
||||||
|
override val mainUrl = "https://slmaxed.com/"
|
||||||
|
override val requiresReferer = true
|
||||||
|
|
||||||
|
// https://slmaxed.com/e/oLvgezw3LjPzbp8E -> oLvgezw3LjPzbp8E
|
||||||
|
val embedRegex = Regex("""/e/([^/]*)""")
|
||||||
|
|
||||||
|
|
||||||
|
data class JsonResponse(
|
||||||
|
@JsonProperty val status: String? = null,
|
||||||
|
@JsonProperty val message: String? = null,
|
||||||
|
@JsonProperty val type: String? = null,
|
||||||
|
@JsonProperty val token: String? = null,
|
||||||
|
@JsonProperty val result: Map<String, Result>? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Result(
|
||||||
|
@JsonProperty val label: String? = null,
|
||||||
|
@JsonProperty val file: String? = null,
|
||||||
|
@JsonProperty val type: String? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink>? {
|
||||||
|
val id = embedRegex.find(url)!!.groupValues[1]
|
||||||
|
val json = app.post(
|
||||||
|
"${mainUrl}api/video/stream/get",
|
||||||
|
requestBody = """{"id":"$id"}""".toRequestBody(RequestBodyTypes.JSON.toMediaTypeOrNull())
|
||||||
|
).parsed<JsonResponse>()
|
||||||
|
return json.result?.mapNotNull {
|
||||||
|
it.value.let { result ->
|
||||||
|
ExtractorLink(
|
||||||
|
this.name,
|
||||||
|
this.name,
|
||||||
|
result.file ?: return@mapNotNull null,
|
||||||
|
url,
|
||||||
|
result.label?.replace("p", "", ignoreCase = true)?.trim()?.toIntOrNull()
|
||||||
|
?: Qualities.Unknown.value,
|
||||||
|
isM3u8 = result.type?.contains("hls", ignoreCase = true) == true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,12 +16,15 @@ import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||||
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
|
||||||
|
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||||
import com.lagradost.nicehttp.NiceResponse
|
import com.lagradost.nicehttp.NiceResponse
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
import kotlin.system.measureTimeMillis
|
import kotlin.system.measureTimeMillis
|
||||||
|
|
||||||
open class SflixProvider : MainAPI() {
|
open class SflixProvider : MainAPI() {
|
||||||
|
@ -342,7 +345,11 @@ open class SflixProvider : MainAPI() {
|
||||||
val extractorData =
|
val extractorData =
|
||||||
"https://ws11.rabbitstream.net/socket.io/?EIO=4&transport=polling"
|
"https://ws11.rabbitstream.net/socket.io/?EIO=4&transport=polling"
|
||||||
|
|
||||||
extractRabbitStream(iframeLink, subtitleCallback, callback, false) { it }
|
if (iframeLink.contains("streamlare", ignoreCase = true)) {
|
||||||
|
loadExtractor(iframeLink, null).forEach(callback)
|
||||||
|
} else {
|
||||||
|
extractRabbitStream(iframeLink, subtitleCallback, callback, false) { it }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -571,18 +578,14 @@ open class SflixProvider : MainAPI() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only scrape servers with these names
|
||||||
fun String?.isValidServer(): Boolean {
|
fun String?.isValidServer(): Boolean {
|
||||||
if (this.isNullOrEmpty()) return false
|
val list = listOf("upcloud", "vidcloud", "streamlare")
|
||||||
if (this.equals("UpCloud", ignoreCase = true) || this.equals(
|
return list.contains(this?.lowercase(Locale.ROOT))
|
||||||
"Vidcloud",
|
|
||||||
ignoreCase = true
|
|
||||||
) || this.equals("RapidStream", ignoreCase = true)
|
|
||||||
) return true
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For re-use in Zoro
|
// For re-use in Zoro
|
||||||
fun Sources.toExtractorLink(
|
private fun Sources.toExtractorLink(
|
||||||
caller: MainAPI,
|
caller: MainAPI,
|
||||||
name: String,
|
name: String,
|
||||||
extractorData: String? = null,
|
extractorData: String? = null,
|
||||||
|
|
|
@ -33,6 +33,17 @@ class WebViewResolver(val interceptUrl: Regex, val additionalUrls: List<Regex> =
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun resolveUsingWebView(
|
||||||
|
url: String,
|
||||||
|
referer: String? = null,
|
||||||
|
method: String = "GET",
|
||||||
|
requestCallBack: (Request) -> Boolean = { false },
|
||||||
|
) : Pair<Request?, List<Request>> {
|
||||||
|
return resolveUsingWebView(
|
||||||
|
requestCreator(method, url, referer = referer), requestCallBack
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param requestCallBack asynchronously return matched requests by either interceptUrl or additionalUrls. If true, destroy WebView.
|
* @param requestCallBack asynchronously return matched requests by either interceptUrl or additionalUrls. If true, destroy WebView.
|
||||||
* @return the final request (by interceptUrl) and all the collected urls (by additionalUrls).
|
* @return the final request (by interceptUrl) and all the collected urls (by additionalUrls).
|
||||||
|
|
|
@ -294,6 +294,7 @@ val extractorApis: Array<ExtractorApi> = arrayOf(
|
||||||
|
|
||||||
YoutubeExtractor(),
|
YoutubeExtractor(),
|
||||||
YoutubeShortLinkExtractor(),
|
YoutubeShortLinkExtractor(),
|
||||||
|
Streamlare()
|
||||||
)
|
)
|
||||||
|
|
||||||
fun getExtractorApiFromName(name: String): ExtractorApi {
|
fun getExtractorApiFromName(name: String): ExtractorApi {
|
||||||
|
|
Loading…
Reference in a new issue