mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	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:
		
							parent
							
								
									96b5c9658d
								
							
						
					
					
						commit
						596f659a29
					
				
					 14 changed files with 112 additions and 56 deletions
				
			
		|  | @ -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( | ||||
|  |  | |||
|  | @ -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()), | ||||
|  |  | |||
|  | @ -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 { | ||||
|  |  | |||
|  | @ -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 | ||||
|     } | ||||
|  |  | |||
|  | @ -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())) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -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) }) | ||||
|  |  | |||
|  | @ -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) { | ||||
|  |  | |||
|  | @ -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() | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue