refactor on m3u8

This commit is contained in:
LagradOst 2022-04-19 01:20:28 +02:00
parent 615b81f600
commit 510411a9bc
15 changed files with 189 additions and 249 deletions

View file

@ -8,7 +8,7 @@ import com.lagradost.cloudstream3.mvvm.safeApiCall
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.M3u8Helper
import com.lagradost.cloudstream3.utils.getQualityFromName
import com.lagradost.cloudstream3.utils.Qualities
import org.jsoup.Jsoup
import org.mozilla.javascript.Context
import org.mozilla.javascript.Scriptable
@ -22,8 +22,6 @@ class AllAnimeProvider : MainAPI() {
override val hasQuickSearch = false
override val hasMainPage = true
private val hlsHelper = M3u8Helper()
private fun getStatus(t: String): ShowStatus {
return when (t) {
"Finished" -> ShowStatus.Completed
@ -319,19 +317,13 @@ class AllAnimeProvider : MainAPI() {
referer: String,
qualityName: String,
): List<ExtractorLink> {
return hlsHelper.m3u8Generation(M3u8Helper.M3u8Stream(m3u8Link, null), true).map { stream ->
val qualityString = if ((stream.quality ?: 0) == 0) "" else "${stream.quality}p"
ExtractorLink(
return M3u8Helper.generateM3u8(
this.name,
"${this.name} - $qualityName $qualityString",
stream.streamUrl,
m3u8Link,
referer,
getQualityFromName(stream.quality.toString()),
true,
stream.headers
name = "${this.name} - $qualityName"
)
}
}
override suspend fun loadLinks(
data: String,
@ -366,7 +358,7 @@ class AllAnimeProvider : MainAPI() {
"",
link,
data,
getQualityFromName("1080"),
Qualities.P1080.value,
false
)
)
@ -396,7 +388,7 @@ class AllAnimeProvider : MainAPI() {
"$apiEndPoint/player?uri=" + (if (URI(server.link).host.isNotEmpty()) server.link else apiEndPoint + URI(
server.link
).path),
getQualityFromName("1080"),
Qualities.P1080.value,
false
)
)

View file

@ -124,35 +124,21 @@ class GogoanimeProvider : MainAPI() {
) {
when {
source.file.contains("m3u8") -> {
M3u8Helper().m3u8Generation(
M3u8Helper.M3u8Stream(
source.file,
headers = mapOf("Referer" to "https://gogoplay4.com")
), true
)
.map { stream ->
val qualityString =
if ((stream.quality ?: 0) == 0) "" else "${stream.quality}p"
sourceCallback(
ExtractorLink(
M3u8Helper.generateM3u8(
mainApiName,
"$mainApiName $qualityString",
stream.streamUrl,
source.file,
mainUrl,
getQualityFromName(stream.quality.toString()),
true
)
)
}
headers = mapOf("Referer" to "https://gogoplay4.com")
).forEach (sourceCallback)
}
source.file.contains("vidstreaming") -> {
sourceCallback.invoke(
ExtractorLink(
mainApiName,
"$mainApiName ${source.label?.replace("0 P", "0p") ?: ""}",
mainApiName,
source.file,
mainUrl,
getQualityFromName(source.label ?: ""),
getQualityFromName(source.label),
isM3u8 = source.type == "hls"
)
)
@ -161,10 +147,10 @@ class GogoanimeProvider : MainAPI() {
sourceCallback.invoke(
ExtractorLink(
mainApiName,
"$mainApiName ${source.label?.replace("0 P", "0p") ?: ""}",
mainApiName,
source.file,
mainUrl,
getQualityFromName(source.label ?: ""),
getQualityFromName(source.label),
isM3u8 = source.type == "hls"
)
)
@ -372,7 +358,7 @@ class GogoanimeProvider : MainAPI() {
callback(
ExtractorLink(
"Gogoanime",
if (qual == "null") "Gogoanime" else "Gogoanime - " + qual + "p",
"Gogoanime",
it.attr("href"),
page.url,
getQualityFromName(qual),

View file

@ -150,7 +150,7 @@ class KawaiifuProvider : MainAPI() {
callback(
ExtractorLink(
"Kawaiifu",
"${it.first} - ${source.second}",
it.first,
source.first,
"",
getQualityFromName(source.second),

View file

@ -333,7 +333,7 @@ class TenshiProvider : MainAPI() {
sources.addAll(qualities.map {
ExtractorLink(
this.name,
"${this.name} $release - " + it.size + "p",
"${this.name} $release",
fixUrl(it.src),
this.mainUrl,
getQualityFromName("${it.size}"),

View file

@ -1,7 +1,10 @@
package com.lagradost.cloudstream3.extractors
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.utils.*
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.M3u8Helper
import com.lagradost.cloudstream3.utils.getQualityFromName
import java.net.URI
class AsianLoad : ExtractorApi() {
@ -17,32 +20,22 @@ class AsianLoad : ExtractorApi() {
val extractedUrl = sourceMatch.groupValues[1]
// Trusting this isn't mp4, may fuck up stuff
if (URI(extractedUrl).path.endsWith(".m3u8")) {
M3u8Helper().m3u8Generation(
M3u8Helper.M3u8Stream(
extractedUrl,
headers = mapOf("referer" to this.url)
), true
)
.forEach { stream ->
extractedLinksList.add(
ExtractorLink(
M3u8Helper.generateM3u8(
name,
name = name,
stream.streamUrl,
extractedUrl,
url,
getQualityFromName(stream.quality?.toString()),
true
)
)
headers = mapOf("referer" to this.url)
).forEach { link ->
extractedLinksList.add(link)
}
} else if (extractedUrl.endsWith(".mp4")) {
extractedLinksList.add(
ExtractorLink(
name,
"$name ${sourceMatch.groupValues[2]}",
name,
extractedUrl,
url.replace(" ", "%20"),
Qualities.Unknown.value,
getQualityFromName(sourceMatch.groupValues[2]),
)
)
}

View file

@ -1,14 +1,10 @@
package com.lagradost.cloudstream3.extractors
import com.lagradost.cloudstream3.apmap
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.network.WebViewResolver
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.M3u8Helper
import com.lagradost.cloudstream3.utils.getQualityFromName
open class GenericM3U8 : ExtractorApi() {
@ -23,21 +19,14 @@ open class GenericM3U8 : ExtractorApi() {
)
)
val sources = mutableListOf<ExtractorLink>()
if (response.url.contains("m3u8")) M3u8Helper().m3u8Generation(
M3u8Helper.M3u8Stream(
response.url,
headers = response.headers.toMap()
), true
)
.map { stream ->
sources.add( ExtractorLink(
if (response.url.contains("m3u8"))
M3u8Helper.generateM3u8(
name,
name = name,
stream.streamUrl,
response.url,
url,
getQualityFromName(stream.quality?.toString()),
true
))
headers = response.headers.toMap()
).forEach { link ->
sources.add(link)
}
return sources
}

View file

@ -1,8 +1,9 @@
package com.lagradost.cloudstream3.extractors
import com.lagradost.cloudstream3.apmap
import com.lagradost.cloudstream3.utils.*
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.M3u8Helper
open class Jawcloud : ExtractorApi() {
@ -14,22 +15,13 @@ open class Jawcloud : ExtractorApi() {
val doc = app.get(url).document
val urlString = doc.select("html body div source").attr("src")
val sources = mutableListOf<ExtractorLink>()
if (urlString.contains("m3u8")) M3u8Helper().m3u8Generation(
M3u8Helper.M3u8Stream(
urlString,
headers = app.get(url).headers.toMap()
), true
)
.map { stream ->
sources.add( ExtractorLink(
if (urlString.contains("m3u8"))
M3u8Helper.generateM3u8(
name,
name = name,
stream.streamUrl,
urlString,
url,
getQualityFromName(stream.quality?.toString()),
true
))
}
headers = app.get(url).headers.toMap()
).forEach { link -> sources.add(link) }
return sources
}
}

View file

@ -8,7 +8,6 @@ import com.lagradost.cloudstream3.utils.AppUtils.parseJson
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.M3u8Helper
import com.lagradost.cloudstream3.utils.getQualityFromName
open class Mcloud : ExtractorApi() {
override var name = "Mcloud"
@ -56,23 +55,13 @@ open class Mcloud : ExtractorApi() {
if (mapped.success)
mapped.media.sources.apmap {
if (it.file.contains("m3u8")) {
M3u8Helper().m3u8Generation(
M3u8Helper.M3u8Stream(
it.file,
headers = app.get(url).headers.toMap()
), true
)
.map { stream ->
sources.add(
ExtractorLink(
M3u8Helper.generateM3u8(
name,
name = name,
stream.streamUrl,
it.file,
url,
getQualityFromName(stream.quality?.toString()),
true
)
)
headers = app.get(url).headers.toMap()
).forEach { link ->
sources.add(link)
}
}
}

View file

@ -1,8 +1,9 @@
package com.lagradost.cloudstream3.extractors
import com.lagradost.cloudstream3.apmap
import com.lagradost.cloudstream3.utils.*
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.M3u8Helper
open class PlayerVoxzer : ExtractorApi() {
@ -16,21 +17,14 @@ open class PlayerVoxzer : ExtractorApi() {
val m3u8regex = Regex("((https:|http:)\\/\\/.*\\.m3u8)")
val sources = mutableListOf<ExtractorLink>()
val listm3 = m3u8regex.find(urltext)?.value
if (listm3?.contains("m3u8") == true) M3u8Helper().m3u8Generation(
M3u8Helper.M3u8Stream(
listm3,
headers = app.get(url).headers.toMap()
), true
)
.map { stream ->
sources.add( ExtractorLink(
if (listm3?.contains("m3u8") == true)
M3u8Helper.generateM3u8(
name,
name = name,
stream.streamUrl,
listm3,
url,
getQualityFromName(stream.quality?.toString()),
true
))
headers = app.get(url).headers.toMap()
).forEach { link ->
sources.add(link)
}
return sources
}

View file

@ -1,11 +1,11 @@
package com.lagradost.cloudstream3.extractors
import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.USER_AGENT
import com.lagradost.cloudstream3.apmap
import com.lagradost.cloudstream3.utils.*
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.M3u8Helper
class StreamSB1 : StreamSB() {
@ -103,23 +103,13 @@ open class StreamSB : ExtractorApi() {
val mapped = urltext.let { parseJson<Main>(it) }
val testurl = app.get(mapped.streamData.file, headers = headers).text
// val urlmain = mapped.streamData.file.substringBefore("/hls/")
if (urltext.contains("m3u8") && testurl.contains("EXTM3U")) return M3u8Helper().m3u8Generation(
M3u8Helper.M3u8Stream(
mapped.streamData.file,
headers = headers
), true
)
.map { stream ->
// val cleanstreamurl = stream.streamUrl.replace(Regex("https://.*/hls/"), "$urlmain/hls/")
ExtractorLink(
if (urltext.contains("m3u8") && testurl.contains("EXTM3U"))
return M3u8Helper.generateM3u8(
name,
name = name,
stream.streamUrl,
mapped.streamData.file,
url,
getQualityFromName(stream.quality?.toString()),
true
headers = headers
)
}
return null
}
}

View file

@ -4,8 +4,7 @@ import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.network.WebViewResolver
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.M3u8Helper
import com.lagradost.cloudstream3.utils.getQualityFromName
import com.lagradost.cloudstream3.utils.M3u8Helper.Companion.generateM3u8
open class WatchSB : ExtractorApi() {
override var name = "WatchSB"
@ -19,21 +18,6 @@ open class WatchSB : ExtractorApi() {
)
)
return M3u8Helper().m3u8Generation(
M3u8Helper.M3u8Stream(
response.url,
headers = response.headers.toMap()
), true
)
.map { stream ->
ExtractorLink(
name,
name = name,
stream.streamUrl,
url,
getQualityFromName(stream.quality?.toString()),
true
)
}
return generateM3u8(name, response.url, url, headers = response.headers.toMap())
}
}

View file

@ -5,11 +5,16 @@ import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.apmap
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.mapper
import com.lagradost.cloudstream3.utils.*
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.M3u8Helper.Companion.generateM3u8
import com.lagradost.cloudstream3.utils.Qualities
import com.lagradost.cloudstream3.utils.getQualityFromName
class Vidstreamz : WcoStream() {
override var mainUrl = "https://vidstreamz.online"
}
class Vizcloud : WcoStream() {
override var mainUrl = "https://vizcloud2.ru"
}
@ -46,14 +51,16 @@ open class WcoStream : ExtractorApi() {
override var name = "VidStream" //Cause works for animekisa and wco
override var mainUrl = "https://vidstream.pro"
override val requiresReferer = false
private val hlsHelper = M3u8Helper()
override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> {
val baseUrl = url.split("/e/")[0]
val html = app.get(url, headers = mapOf("Referer" to "https://wcostream.cc/")).text
val (Id) = (Regex("/e/(.*?)?domain").find(url)?.destructured ?: Regex("""/e/(.*)""").find(url)?.destructured) ?: return emptyList()
val (skey) = Regex("""skey\s=\s['"](.*?)['"];""").find(html)?.destructured ?: return emptyList()
val (Id) = (Regex("/e/(.*?)?domain").find(url)?.destructured ?: Regex("""/e/(.*)""").find(
url
)?.destructured) ?: return emptyList()
val (skey) = Regex("""skey\s=\s['"](.*?)['"];""").find(html)?.destructured
?: return emptyList()
val apiLink = "$baseUrl/info/$Id?domain=wcostream.cc&skey=$skey"
val referrer = "$baseUrl/e/$Id?domain=wcostream.cc"
@ -92,7 +99,8 @@ open class WcoStream : ExtractorApi() {
link720,
link480,
link360,
linkauto).apmap { serverurl ->
linkauto
).apmap { serverurl ->
val testurl = app.get(serverurl, headers = mapOf("Referer" to url)).text
if (testurl.contains("EXTM3")) {
val quality = if (serverurl.contains("H4")) "1080p"
@ -116,22 +124,15 @@ open class WcoStream : ExtractorApi() {
}
if (mainUrl == "https://vidstream.pro" || mainUrl == "https://vidstreamz.online" || mainUrl == "https://vizcloud2.online"
|| mainUrl == "https://vizcloud.xyz" || mainUrl == "https://vizcloud.live" || mainUrl == "https://vizcloud.info"
|| mainUrl == "https://mwvn.vizcloud.info" || mainUrl == "https://vizcloud.digital") {
|| mainUrl == "https://mwvn.vizcloud.info" || mainUrl == "https://vizcloud.digital"
) {
if (it.file.contains("m3u8")) {
hlsHelper.m3u8Generation(M3u8Helper.M3u8Stream(it.file.replace("#.mp4",""), null,
headers = mapOf("Referer" to url)), true)
.forEach { stream ->
sources.add(
ExtractorLink(
generateM3u8(
name,
name = name,
stream.streamUrl,
it.file.replace("#.mp4", ""),
url,
getQualityFromName(stream.quality?.toString()),
true,
headers = mapOf("Referer" to url)
)
)
}
} else {
sources.add(
ExtractorLink(

View file

@ -2,7 +2,10 @@ package com.lagradost.cloudstream3.extractors
import com.lagradost.cloudstream3.apmap
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.utils.*
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.M3u8Helper
import com.lagradost.cloudstream3.utils.getAndUnpack
class Zplayer: ZplayerV2() {
override var name: String = "Zplayer"
@ -37,21 +40,13 @@ open class ZplayerV2 : ExtractorApi() {
if (urlm3u8.contains("m3u8")) {
val testurl = app.get(urlm3u8, headers = mapOf("Referer" to url)).text
if (testurl.contains("EXTM3U")) {
M3u8Helper().m3u8Generation(
M3u8Helper.M3u8Stream(
M3u8Helper.generateM3u8(
name,
urlm3u8,
headers = mapOf("Referer" to url)
), true
)
.map { stream ->
sources.add( ExtractorLink(
source = name,
name = name,
stream.streamUrl,
url,
getQualityFromName(stream.quality?.toString()),
true
))
headers = mapOf("Referer" to url)
).forEach { link ->
sources.add(link)
}
}
}

View file

@ -3,7 +3,6 @@ package com.lagradost.cloudstream3.movieproviders
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.M3u8Helper
import com.lagradost.cloudstream3.utils.getQualityFromName
import com.lagradost.cloudstream3.utils.loadExtractor
import org.jsoup.Jsoup
@ -204,25 +203,14 @@ open class PelisplusProviderTemplate : MainAPI() {
val soup = app.get(link).text
val m3u8regex = Regex("((https:|http:)\\/\\/.*m3u8.*expiry=(\\d+))")
val m3u8 = m3u8regex.find(soup)?.value ?: return false
M3u8Helper().m3u8Generation(
M3u8Helper.M3u8Stream(
m3u8,
headers = mapOf("Referer" to mainUrl)
), true
)
.map { stream ->
val qualityString = if ((stream.quality ?: 0) == 0) "" else "${stream.quality}p"
callback(
ExtractorLink(
M3u8Helper.generateM3u8(
name,
"$name $qualityString",
stream.streamUrl,
m3u8,
mainUrl,
getQualityFromName(stream.quality.toString()),
true
)
)
}
headers = mapOf("Referer" to mainUrl)
).forEach (callback)
return true
}

View file

@ -10,13 +10,47 @@ import kotlin.math.pow
class M3u8Helper {
companion object {
private val generator = M3u8Helper()
fun generateM3u8(
source: String,
streamUrl: String,
referer: String,
quality: Int? = null,
headers: Map<String, String> = mapOf(),
name: String = source
): List<ExtractorLink> {
return generator.m3u8Generation(
M3u8Stream(
streamUrl = streamUrl,
quality = quality,
headers = headers,
), true
)
.map { stream ->
ExtractorLink(
source,
name = name,
stream.streamUrl,
referer,
stream.quality ?: Qualities.Unknown.value,
true,
stream.headers,
)
}
}
}
private val ENCRYPTION_DETECTION_REGEX = Regex("#EXT-X-KEY:METHOD=([^,]+),")
private val ENCRYPTION_URL_IV_REGEX = Regex("#EXT-X-KEY:METHOD=([^,]+),URI=\"([^\"]+)\"(?:,IV=(.*))?")
private val ENCRYPTION_URL_IV_REGEX =
Regex("#EXT-X-KEY:METHOD=([^,]+),URI=\"([^\"]+)\"(?:,IV=(.*))?")
private val QUALITY_REGEX =
Regex("""#EXT-X-STREAM-INF:(?:(?:.*?(?:RESOLUTION=\d+x(\d+)).*?\s+(.*))|(?:.*?\s+(.*)))""")
private val TS_EXTENSION_REGEX = Regex("""(.*\.ts.*|.*\.jpg.*)""") //.jpg here 'case vizcloud uses .jpg instead of .ts
private val TS_EXTENSION_REGEX =
Regex("""(.*\.ts.*|.*\.jpg.*)""") //.jpg here 'case vizcloud uses .jpg instead of .ts
fun absoluteExtensionDetermination(url: String): String? {
private fun absoluteExtensionDetermination(url: String): String? {
val split = url.split("/")
val gg: String = split[split.size - 1].split("?")[0]
return if (gg.contains(".")) {
@ -40,7 +74,11 @@ class M3u8Helper {
}
}.iterator()
private fun getDecrypter(secretKey: ByteArray, data: ByteArray, iv: ByteArray = "".toByteArray()): ByteArray {
private fun getDecrypter(
secretKey: ByteArray,
data: ByteArray,
iv: ByteArray = "".toByteArray()
): ByteArray {
val ivKey = if (iv.isEmpty()) defaultIvGen.next() else iv
val c = Cipher.getInstance("AES/CBC/PKCS5Padding")
val skSpec = SecretKeySpec(secretKey, "AES")
@ -135,7 +173,14 @@ class M3u8Helper {
)
fun hlsYield(qualities: List<M3u8Stream>, startIndex: Int = 0): Iterator<HlsDownloadData> {
if (qualities.isEmpty()) return listOf(HlsDownloadData(byteArrayOf(), 1, 1, true)).iterator()
if (qualities.isEmpty()) return listOf(
HlsDownloadData(
byteArrayOf(),
1,
1,
true
)
).iterator()
var selected = selectBest(qualities)
if (selected == null) {
@ -148,7 +193,8 @@ class M3u8Helper {
val secondSelection = selectBest(streams.ifEmpty { listOf(selected) })
if (secondSelection != null) {
val m3u8Response = runBlocking {app.get(secondSelection.streamUrl, headers = headers).text}
val m3u8Response =
runBlocking { app.get(secondSelection.streamUrl, headers = headers).text }
var encryptionUri: String?
var encryptionIv = byteArrayOf()
@ -166,7 +212,8 @@ class M3u8Helper {
}
encryptionIv = match.component3().toByteArray()
val encryptionKeyResponse = runBlocking { app.get(encryptionUri, headers = headers) }
val encryptionKeyResponse =
runBlocking { app.get(encryptionUri, headers = headers) }
encryptionData = encryptionKeyResponse.body?.bytes() ?: byteArrayOf()
}