Added sflix downloads, fixed some sflix sources and added image caching (#128)

Waited long enough and it seems to work fine, I will just revert if this fucks up :)
This commit is contained in:
LagradOst 2021-10-07 19:40:31 +02:00 committed by GitHub
parent 96b5c9658d
commit 596f659a29
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 112 additions and 56 deletions

View file

@ -15,10 +15,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 8
- name: Set up JDK 11
uses: actions/setup-java@v2
with:
java-version: '8'
java-version: '11'
distribution: 'adopt'
- name: Grant execute permission for gradlew
run: chmod +x gradlew

View file

@ -7,10 +7,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 8
- name: Set up JDK 11
uses: actions/setup-java@v2
with:
java-version: '8'
java-version: '11'
distribution: 'adopt'
- name: Grant execute permission for gradlew
run: chmod +x gradlew

View file

@ -4,6 +4,7 @@
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="delegatedBuild" value="true" />
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="11" project-jdk-type="JavaSDK" />
</project>

View file

@ -35,7 +35,7 @@ android {
minSdkVersion 21
targetSdkVersion 31
versionCode 27
versionName "1.9.11"
versionName "1.9.12"
resValue "string", "app_version",
"${defaultConfig.versionName}${versionNameSuffix ?: ""}"
@ -105,6 +105,8 @@ dependencies {
implementation "androidx.preference:preference-ktx:1.1.1"
implementation 'com.github.bumptech.glide:glide:4.12.0'
kapt 'com.github.bumptech.glide:compiler:4.12.0'
implementation 'jp.wasabeef:glide-transformations:4.0.0'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'

View file

@ -3,10 +3,7 @@ package com.lagradost.cloudstream3.extractors
import com.lagradost.cloudstream3.network.get
import com.lagradost.cloudstream3.network.text
import com.lagradost.cloudstream3.network.url
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities
import com.lagradost.cloudstream3.utils.getQualityFromName
import com.lagradost.cloudstream3.utils.*
import java.net.URI
class AsianLoad : ExtractorApi() {
@ -17,8 +14,6 @@ class AsianLoad : ExtractorApi() {
override val requiresReferer: Boolean
get() = true
private val urlRegex = Regex("""(.*?)([^/]+$)""")
private val m3u8UrlRegex = Regex("""RESOLUTION=\d*x(\d*).*\n(.*\.m3u8)""")
private val sourceRegex = Regex("""sources:[\W\w]*?file:\s*?["'](.*?)["']""")
override fun getUrl(url: String, referer: String?): List<ExtractorLink> {
val extractedLinksList: MutableList<ExtractorLink> = mutableListOf()
@ -27,21 +22,25 @@ class AsianLoad : ExtractorApi() {
val extractedUrl = sourceMatch.groupValues[1]
// Trusting this isn't mp4, may fuck up stuff
if (URI(extractedUrl).path.endsWith(".m3u8")) {
with(get(extractedUrl, referer = this.url)) {
m3u8UrlRegex.findAll(this.text).forEach { match ->
M3u8Helper().m3u8Generation(
M3u8Helper.M3u8Stream(
extractedUrl,
headers = mapOf("referer" to this.url)
), true
)
.forEach { stream ->
val qualityString = if ((stream.quality ?: 0) == 0) "" else "${stream.quality}p"
extractedLinksList.add(
ExtractorLink(
name,
"$name ${match.groupValues[1]}p",
urlRegex.find(this.url)!!.groupValues[1] + match.groupValues[2],
"$name $qualityString",
stream.streamUrl,
url,
getQualityFromName(match.groupValues[1]),
isM3u8 = true
getQualityFromName(stream.quality.toString()),
true
)
)
}
}
} else if (extractedUrl.endsWith(".mp4")) {
extractedLinksList.add(
ExtractorLink(

View file

@ -45,11 +45,12 @@ class WcoStream : ExtractorApi() {
if (mapped.success) {
mapped.media.sources.forEach {
if (it.file.contains("m3u8")) {
hlsHelper.m3u8Generation(M3u8Helper.M3u8Stream(it.file, null)).forEach { stream ->
hlsHelper.m3u8Generation(M3u8Helper.M3u8Stream(it.file, null), true).forEach { stream ->
val qualityString = if ((stream.quality ?: 0) == 0) "" else "${stream.quality}p"
sources.add(
ExtractorLink(
name,
name + if (stream.quality != null) " - ${stream.quality}" else "",
"$name $qualityString",
stream.streamUrl,
"",
getQualityFromName(stream.quality.toString()),

View file

@ -8,6 +8,7 @@ import com.lagradost.cloudstream3.network.WebViewResolver
import com.lagradost.cloudstream3.network.get
import com.lagradost.cloudstream3.network.text
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.M3u8Helper
import com.lagradost.cloudstream3.utils.getQualityFromName
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
@ -29,7 +30,7 @@ class SflixProvider : MainAPI() {
get() = true
override val hasDownloadSupport: Boolean
get() = false
get() = true
override val supportedTypes: Set<TvType>
get() = setOf(
@ -257,21 +258,39 @@ class SflixProvider : MainAPI() {
)
data class SourceObject(
@JsonProperty("sources") val sources: List<Sources1?>?,
@JsonProperty("sources_1") val sources1: List<Sources1?>?,
@JsonProperty("sources_2") val sources2: List<Sources1?>?,
@JsonProperty("sourcesBackup") val sourcesBackup: List<Sources1?>?,
@JsonProperty("tracks") val tracks: List<Tracks?>?
)
private fun Sources1.toExtractorLink(): ExtractorLink? {
private fun Sources1.toExtractorLink(name: String): List<ExtractorLink>? {
return this.file?.let {
ExtractorLink(
this@SflixProvider.name,
this.label?.let { "${this@SflixProvider.name} - $it" } ?: this@SflixProvider.name,
it,
this@SflixProvider.mainUrl,
getQualityFromName(this.label ?: ""),
URI(this.file).path.endsWith(".m3u8") || this.label.equals("hls", ignoreCase = true),
)
val isM3u8 = URI(this.file).path.endsWith(".m3u8") || this.type.equals("hls", ignoreCase = true)
if (isM3u8) {
M3u8Helper().m3u8Generation(M3u8Helper.M3u8Stream(this.file, null), true).map { stream ->
val qualityString = if ((stream.quality ?: 0) == 0) label ?: "" else "${stream.quality}p"
ExtractorLink(
this@SflixProvider.name,
"${this@SflixProvider.name} $qualityString $name",
stream.streamUrl,
mainUrl,
getQualityFromName(stream.quality.toString()),
true
)
}
} else {
listOf(ExtractorLink(
this@SflixProvider.name,
this.label?.let { "${this@SflixProvider.name} - $it" } ?: this@SflixProvider.name,
it,
this@SflixProvider.mainUrl,
getQualityFromName(this.type ?: ""),
false,
))
}
}
}
@ -319,18 +338,15 @@ class SflixProvider : MainAPI() {
val mapped = mapper.readValue<SourceObject>(sources)
mapped.sources1?.forEach {
it?.toExtractorLink()?.let { extractorLink ->
callback.invoke(
extractorLink
)
}
}
mapped.sources2?.forEach {
it?.toExtractorLink()?.let { extractorLink ->
callback.invoke(
extractorLink
)
val list = listOf(
mapped.sources1 to "source 1",
mapped.sources2 to "source 2",
mapped.sources to "source 0",
mapped.sourcesBackup to "source 3"
)
list.forEach { subList ->
subList.first?.forEach {
it?.toExtractorLink(subList.second)?.forEach(callback)
}
}
mapped.tracks?.forEach {

View file

@ -1,10 +1,8 @@
package com.lagradost.cloudstream3.network
import android.annotation.SuppressLint
import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
import android.webkit.WebView
import android.webkit.WebViewClient
import android.net.http.SslError
import android.webkit.*
import com.lagradost.cloudstream3.AcraApplication
import com.lagradost.cloudstream3.utils.Coroutines.main
import kotlinx.coroutines.delay
@ -26,6 +24,7 @@ class WebViewResolver(val interceptUrl: Regex) : Interceptor {
@SuppressLint("SetJavaScriptEnabled")
suspend fun resolveUsingWebView(request: Request): Request? {
val url = request.url.toString()
println("Initial web-view request: $url")
var webView: WebView? = null
fun destroyWebView() {
@ -43,6 +42,7 @@ class WebViewResolver(val interceptUrl: Regex) : Interceptor {
webView = WebView(
AcraApplication.context ?: throw RuntimeException("No base context in WebViewResolver")
).apply {
settings.cacheMode
settings.javaScriptEnabled = true
}
@ -62,10 +62,15 @@ class WebViewResolver(val interceptUrl: Regex) : Interceptor {
10,
TimeUnit.MINUTES
)
println("Web-view request finished: $webViewUrl")
destroyWebView()
}
return super.shouldInterceptRequest(view, request)
}
override fun onReceivedSslError(view: WebView?, handler: SslErrorHandler?, error: SslError?) {
handler?.proceed() // Ignore ssl issues
}
}
webView?.loadUrl(url)
@ -83,6 +88,7 @@ class WebViewResolver(val interceptUrl: Regex) : Interceptor {
loop += 1
}
println("Web-view timeout after ${totalTime / 1000}s")
destroyWebView()
return null
}

View file

@ -0,0 +1,21 @@
package com.lagradost.cloudstream3.utils
import android.content.Context
import com.bumptech.glide.GlideBuilder
import com.bumptech.glide.annotation.GlideModule
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.module.AppGlideModule
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.signature.ObjectKey
@GlideModule
class GlideModule : AppGlideModule() {
override fun applyOptions(context: Context, builder: GlideBuilder) {
super.applyOptions(context, builder)
builder.apply {
RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.signature(ObjectKey(System.currentTimeMillis().toShort()))
}
}
}

View file

@ -12,7 +12,8 @@ import kotlin.math.pow
class M3u8Helper {
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 QUALITY_REGEX = Regex("""#EXT-X-STREAM-INF:(?:(?:.*?(?:RESOLUTION=\d+x(\d+)).*?\s+(.*))|(?:.*?\s+(.*)))""")
private val QUALITY_REGEX =
Regex("""#EXT-X-STREAM-INF:(?:(?:.*?(?:RESOLUTION=\d+x(\d+)).*?\s+(.*))|(?:.*?\s+(.*)))""")
private val TS_EXTENSION_REGEX = Regex("""(.*\.ts.*)""")
fun absoluteExtensionDetermination(url: String): String? {
@ -78,7 +79,7 @@ class M3u8Helper {
return !url.contains("https://") && !url.contains("http://")
}
fun m3u8Generation(m3u8: M3u8Stream): List<M3u8Stream> {
fun m3u8Generation(m3u8: M3u8Stream, returnThis: Boolean): List<M3u8Stream> {
val generate = sequence {
val m3u8Parent = getParentLink(m3u8.streamUrl)
val response = get(m3u8.streamUrl, headers = m3u8.headers).text
@ -99,7 +100,7 @@ class M3u8Helper {
m3u8Link,
quality.toIntOrNull(),
m3u8.headers
)
), false
)
)
}
@ -111,6 +112,15 @@ class M3u8Helper {
)
)
}
if (returnThis) {
yield(
M3u8Stream(
m3u8.streamUrl,
0,
m3u8.headers
)
)
}
}
return generate.toList()
}
@ -131,7 +141,7 @@ class M3u8Helper {
}
val headers = selected.headers
val streams = qualities.map { m3u8Generation(it) }.flatten()
val streams = qualities.map { m3u8Generation(it, false) }.flatten()
//val sslVerification = if (headers.containsKey("ssl_verification")) headers["ssl_verification"].toBoolean() else true
val secondSelection = selectBest(streams.ifEmpty { listOf(selected) })

View file

@ -96,7 +96,7 @@ object UIHelper {
fun ImageView?.setImage(url : String?) {
if(this == null || url.isNullOrBlank()) return
try {
Glide.with(this.context)
GlideApp.with(this.context)
.load(GlideUrl(url))
.into(this)
} catch (e : Exception) {

View file

@ -202,7 +202,7 @@ object VideoDownloadManager {
return cachedBitmaps[url]
}
val bitmap = Glide.with(this)
val bitmap = GlideApp.with(this)
.asBitmap()
.load(url).into(720, 720)
.get()