diff --git a/.github/workflows/prerelease.yml b/.github/workflows/prerelease.yml
index 00242ccc..5ab95416 100644
--- a/.github/workflows/prerelease.yml
+++ b/.github/workflows/prerelease.yml
@@ -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
diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml
index 281bb10b..1a4db134 100644
--- a/.github/workflows/pull_request.yml
+++ b/.github/workflows/pull_request.yml
@@ -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
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index fb7f4a8a..5421743a 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -3,4 +3,4 @@
-
\ No newline at end of file
+
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index ada5a4e9..c525ac92 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -4,6 +4,7 @@
-
\ No newline at end of file
+
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 4bc4fc6e..25d34a47 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 908ff43b..e41c48e0 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -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'
diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/AsianLoad.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/AsianLoad.kt
index 7ad7105c..2c087b10 100644
--- a/app/src/main/java/com/lagradost/cloudstream3/extractors/AsianLoad.kt
+++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/AsianLoad.kt
@@ -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 {
val extractedLinksList: MutableList = 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(
diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/WcoStream.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/WcoStream.kt
index 587bb376..c239e4f5 100644
--- a/app/src/main/java/com/lagradost/cloudstream3/extractors/WcoStream.kt
+++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/WcoStream.kt
@@ -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()),
diff --git a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/SflixProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/SflixProvider.kt
index 74dc91b4..f36607e9 100644
--- a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/SflixProvider.kt
+++ b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/SflixProvider.kt
@@ -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
get() = setOf(
@@ -257,21 +258,39 @@ class SflixProvider : MainAPI() {
)
data class SourceObject(
+ @JsonProperty("sources") val sources: List?,
@JsonProperty("sources_1") val sources1: List?,
@JsonProperty("sources_2") val sources2: List?,
+ @JsonProperty("sourcesBackup") val sourcesBackup: List?,
@JsonProperty("tracks") val tracks: List?
)
- private fun Sources1.toExtractorLink(): ExtractorLink? {
+ private fun Sources1.toExtractorLink(name: String): List? {
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(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 {
diff --git a/app/src/main/java/com/lagradost/cloudstream3/network/WebViewResolver.kt b/app/src/main/java/com/lagradost/cloudstream3/network/WebViewResolver.kt
index ff2e061c..952d1d59 100644
--- a/app/src/main/java/com/lagradost/cloudstream3/network/WebViewResolver.kt
+++ b/app/src/main/java/com/lagradost/cloudstream3/network/WebViewResolver.kt
@@ -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
}
diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/GlideApp.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/GlideApp.kt
new file mode 100644
index 00000000..b9731742
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/utils/GlideApp.kt
@@ -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()))
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/M3u8Helper.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/M3u8Helper.kt
index 108b1a2a..2cf81f6b 100644
--- a/app/src/main/java/com/lagradost/cloudstream3/utils/M3u8Helper.kt
+++ b/app/src/main/java/com/lagradost/cloudstream3/utils/M3u8Helper.kt
@@ -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 {
+ fun m3u8Generation(m3u8: M3u8Stream, returnThis: Boolean): List {
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) })
diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/UIHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/UIHelper.kt
index b314f29b..9cfe71d5 100644
--- a/app/src/main/java/com/lagradost/cloudstream3/utils/UIHelper.kt
+++ b/app/src/main/java/com/lagradost/cloudstream3/utils/UIHelper.kt
@@ -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) {
diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt
index 453da090..ed24ee5e 100644
--- a/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt
+++ b/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt
@@ -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()