forked from recloudstream/cloudstream
		
	Merge remote-tracking branch 'origin/master'
This commit is contained in:
		
						commit
						ce8d91684f
					
				
					 5 changed files with 105 additions and 53 deletions
				
			
		|  | @ -8,6 +8,7 @@ import com.lagradost.cloudstream3.movieproviders.SflixProvider.Companion.toExtra | ||||||
| import com.lagradost.cloudstream3.movieproviders.SflixProvider.Companion.toSubtitleFile | import com.lagradost.cloudstream3.movieproviders.SflixProvider.Companion.toSubtitleFile | ||||||
| import com.lagradost.cloudstream3.network.WebViewResolver | import com.lagradost.cloudstream3.network.WebViewResolver | ||||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
|  | import com.lagradost.cloudstream3.utils.loadExtractor | ||||||
| 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 | ||||||
|  | @ -152,7 +153,8 @@ class ZoroProvider : MainAPI() { | ||||||
|                 EnumSet.of(DubStatus.Subbed) |                 EnumSet.of(DubStatus.Subbed) | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             val tvType = getType(it.selectFirst(".film-detail > .fd-infor > .fdi-item")?.text().toString()) |             val tvType = | ||||||
|  |                 getType(it.selectFirst(".film-detail > .fd-infor > .fdi-item")?.text().toString()) | ||||||
|             val href = fixUrl(it.selectFirst(".film-name a").attr("href")) |             val href = fixUrl(it.selectFirst(".film-name a").attr("href")) | ||||||
| 
 | 
 | ||||||
|             AnimeSearchResponse( |             AnimeSearchResponse( | ||||||
|  | @ -187,7 +189,8 @@ class ZoroProvider : MainAPI() { | ||||||
|             when { |             when { | ||||||
|                 (year != null && japaneseTitle != null && status != null) -> break |                 (year != null && japaneseTitle != null && status != null) -> break | ||||||
|                 text.contains("Premiered") && year == null -> |                 text.contains("Premiered") && year == null -> | ||||||
|                     year = info.selectFirst(".name")?.text().toString().split(" ").last().toIntOrNull() |                     year = | ||||||
|  |                         info.selectFirst(".name")?.text().toString().split(" ").last().toIntOrNull() | ||||||
| 
 | 
 | ||||||
|                 text.contains("Japanese") && japaneseTitle == null -> |                 text.contains("Japanese") && japaneseTitle == null -> | ||||||
|                     japaneseTitle = info.selectFirst(".name")?.text().toString() |                     japaneseTitle = info.selectFirst(".name")?.text().toString() | ||||||
|  | @ -255,44 +258,40 @@ class ZoroProvider : MainAPI() { | ||||||
|         callback: (ExtractorLink) -> Unit |         callback: (ExtractorLink) -> Unit | ||||||
|     ): Boolean { |     ): Boolean { | ||||||
| 
 | 
 | ||||||
|         // Copy pasted from Sflix :) |  | ||||||
| 
 |  | ||||||
|         val servers: List<Pair<DubStatus, String>> = Jsoup.parse( |         val servers: List<Pair<DubStatus, String>> = Jsoup.parse( | ||||||
|             mapper.readValue<Response>( |             app.get("$mainUrl/ajax/v2/episode/servers?episodeId=" + data.split("=")[1]) | ||||||
|                 app.get("$mainUrl/ajax/v2/episode/servers?episodeId=" + data.split("=")[1]).text |                 .mapped<Response>().html | ||||||
|             ).html |  | ||||||
|         ).select(".server-item[data-type][data-id]").map { |         ).select(".server-item[data-type][data-id]").map { | ||||||
|             Pair(if (it.attr("data-type") == "sub") DubStatus.Subbed else DubStatus.Dubbed, it.attr("data-id")!!) |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         val res = app.get( |  | ||||||
|             data, |  | ||||||
|             interceptor = WebViewResolver( |  | ||||||
|                 Regex("""/getSources""") |  | ||||||
|             ) |  | ||||||
|         ) |  | ||||||
| //        println("RES TEXT ${res.text}") |  | ||||||
| 
 |  | ||||||
|         val recaptchaToken = res.response.request.url.queryParameter("_token") |  | ||||||
| 
 |  | ||||||
|         val responses = servers.map { |  | ||||||
|             val link = "$mainUrl/ajax/v2/episode/sources?id=${it.second}&_token=$recaptchaToken" |  | ||||||
|             Pair( |             Pair( | ||||||
|                 it.first, |                 if (it.attr("data-type") == "sub") DubStatus.Subbed else DubStatus.Dubbed, | ||||||
|                 getM3u8FromRapidCloud( |                 it.attr("data-id")!! | ||||||
|                     mapper.readValue<RapidCloudResponse>( |  | ||||||
|                         app.get( |  | ||||||
|                             link, |  | ||||||
|                             res.headers.toMap() |  | ||||||
|                         ).text |  | ||||||
|                     ).link |  | ||||||
|                 ) |  | ||||||
|             ) |             ) | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         responses.forEach { |         // Prevent duplicates | ||||||
|             if (it.second.contains("<html")) return@forEach |         servers.distinctBy { it.second }.pmap { | ||||||
|             val mapped = mapper.readValue<SflixProvider.SourceObject>(it.second) |             val link = | ||||||
|  |                 "$mainUrl/ajax/v2/episode/sources?id=${it.second}" | ||||||
|  |             val extractorLink = app.get( | ||||||
|  |                 link, | ||||||
|  |             ).mapped<RapidCloudResponse>().link | ||||||
|  | 
 | ||||||
|  |             // Loads the links in the appropriate extractor. | ||||||
|  |             val hasLoadedExtractorLink = loadExtractor(extractorLink, mainUrl, callback) | ||||||
|  | 
 | ||||||
|  |             if (!hasLoadedExtractorLink) { | ||||||
|  | 
 | ||||||
|  |                 // Not an extractor because: | ||||||
|  |                 // 1. No subtitle callback | ||||||
|  |                 // 2. Missing dub/sub status in parameter (might be substituted in the referer) | ||||||
|  | 
 | ||||||
|  |                 val response = | ||||||
|  |                     getM3u8FromRapidCloud( | ||||||
|  |                         extractorLink | ||||||
|  |                     ) | ||||||
|  | 
 | ||||||
|  |                 if (response.contains("<html")) return@pmap | ||||||
|  |                 val mapped = mapper.readValue<SflixProvider.SourceObject>(response) | ||||||
| 
 | 
 | ||||||
|                 mapped.tracks?.forEach { track -> |                 mapped.tracks?.forEach { track -> | ||||||
|                     track?.toSubtitleFile()?.let { subtitleFile -> |                     track?.toSubtitleFile()?.let { subtitleFile -> | ||||||
|  | @ -309,7 +308,9 @@ class ZoroProvider : MainAPI() { | ||||||
| 
 | 
 | ||||||
|                 list.forEach { subList -> |                 list.forEach { subList -> | ||||||
|                     subList.first?.forEach { a -> |                     subList.first?.forEach { a -> | ||||||
|                     a?.toExtractorLink(this, subList.second + " - ${it.first}")?.forEach(callback) |                         a?.toExtractorLink(this, subList.second + " - ${it.first}") | ||||||
|  |                             ?.forEach(callback) | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -0,0 +1,45 @@ | ||||||
|  | package com.lagradost.cloudstream3.extractors | ||||||
|  | 
 | ||||||
|  | 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 | ||||||
|  | 
 | ||||||
|  | class WatchSB : ExtractorApi() { | ||||||
|  |     override val name: String | ||||||
|  |         get() = "WatchSB" | ||||||
|  |     override val mainUrl: String | ||||||
|  |         get() = "https://watchsb.com" | ||||||
|  |     override val requiresReferer: Boolean | ||||||
|  |         get() = false | ||||||
|  | 
 | ||||||
|  |     override fun getUrl(url: String, referer: String?): List<ExtractorLink> { | ||||||
|  |         val response = app.get( | ||||||
|  |             url, interceptor = WebViewResolver( | ||||||
|  |                 Regex("""master\.m3u8""") | ||||||
|  |             ) | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         val extractedLinksList = M3u8Helper().m3u8Generation( | ||||||
|  |             M3u8Helper.M3u8Stream( | ||||||
|  |                 response.url, | ||||||
|  |                 headers = response.headers.toMap() | ||||||
|  |             ), true | ||||||
|  |         ) | ||||||
|  |             .map { stream -> | ||||||
|  |                 val qualityString = if ((stream.quality ?: 0) == 0) "" else "${stream.quality}p" | ||||||
|  |                 ExtractorLink( | ||||||
|  |                     name, | ||||||
|  |                     "$name $qualityString", | ||||||
|  |                     stream.streamUrl, | ||||||
|  |                     url, | ||||||
|  |                     getQualityFromName(stream.quality.toString()), | ||||||
|  |                     true | ||||||
|  |                 ) | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |         return extractedLinksList | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -9,6 +9,8 @@ import com.lagradost.cloudstream3.app | ||||||
| import com.lagradost.cloudstream3.mapper | import com.lagradost.cloudstream3.mapper | ||||||
| import okhttp3.* | import okhttp3.* | ||||||
| import okhttp3.Headers.Companion.toHeaders | import okhttp3.Headers.Companion.toHeaders | ||||||
|  | import org.jsoup.Jsoup | ||||||
|  | import org.jsoup.nodes.Document | ||||||
| import java.io.File | import java.io.File | ||||||
| import java.net.URI | import java.net.URI | ||||||
| import java.util.* | import java.util.* | ||||||
|  | @ -78,6 +80,7 @@ class AppResponse( | ||||||
|     val body by lazy { response.body } |     val body by lazy { response.body } | ||||||
|     val code = response.code |     val code = response.code | ||||||
|     val headers = response.headers |     val headers = response.headers | ||||||
|  |     val document: Document by lazy { Jsoup.parse(text) } | ||||||
| 
 | 
 | ||||||
|     /** Same as using mapper.readValue<T>() */ |     /** Same as using mapper.readValue<T>() */ | ||||||
|     inline fun <reified T : Any> mapped(): T { |     inline fun <reified T : Any> mapped(): T { | ||||||
|  |  | ||||||
|  | @ -745,9 +745,7 @@ class PlayerFragment : Fragment() { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private fun safeReleasePlayer() { |     private fun safeReleasePlayer() { | ||||||
|         thread { |  | ||||||
|         simpleCache?.release() |         simpleCache?.release() | ||||||
|         } |  | ||||||
|         if (this::exoPlayer.isInitialized) { |         if (this::exoPlayer.isInitialized) { | ||||||
|             exoPlayer.release() |             exoPlayer.release() | ||||||
|         } |         } | ||||||
|  | @ -1969,7 +1967,6 @@ class PlayerFragment : Fragment() { | ||||||
|         // torrentStream?.stopStream() |         // torrentStream?.stopStream() | ||||||
|         // torrentStream = null |         // torrentStream = null | ||||||
| 
 | 
 | ||||||
|         super.onDestroy() |  | ||||||
|         canEnterPipMode = false |         canEnterPipMode = false | ||||||
| 
 | 
 | ||||||
|         savePositionInPlayer() |         savePositionInPlayer() | ||||||
|  | @ -1979,6 +1976,7 @@ class PlayerFragment : Fragment() { | ||||||
| 
 | 
 | ||||||
|         activity?.showSystemUI() |         activity?.showSystemUI() | ||||||
|         activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER |         activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER | ||||||
|  |         super.onDestroy() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override fun onPause() { |     override fun onPause() { | ||||||
|  |  | ||||||
|  | @ -58,13 +58,17 @@ fun getAndUnpack(string: String): String { | ||||||
|     return JsUnpacker(packedText).unpack() ?: string |     return JsUnpacker(packedText).unpack() ?: string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fun loadExtractor(url: String, referer: String?, callback: (ExtractorLink) -> Unit) { | /** | ||||||
|  |  * Tries to load the appropriate extractor based on link, returns true if any extractor is loaded. | ||||||
|  |  * */ | ||||||
|  | fun loadExtractor(url: String, referer: String?, callback: (ExtractorLink) -> Unit) : Boolean { | ||||||
|     for (extractor in extractorApis) { |     for (extractor in extractorApis) { | ||||||
|         if (url.startsWith(extractor.mainUrl)) { |         if (url.startsWith(extractor.mainUrl)) { | ||||||
|             extractor.getSafeUrl(url, referer)?.forEach(callback) |             extractor.getSafeUrl(url, referer)?.forEach(callback) | ||||||
|             return |             return true | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |     return false | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| val extractorApis: Array<ExtractorApi> = arrayOf( | val extractorApis: Array<ExtractorApi> = arrayOf( | ||||||
|  | @ -78,6 +82,7 @@ val extractorApis: Array<ExtractorApi> = arrayOf( | ||||||
|     Streamhub(), |     Streamhub(), | ||||||
|     SBPlay(), |     SBPlay(), | ||||||
|     FEmbed(), |     FEmbed(), | ||||||
|  |     WatchSB(), | ||||||
| 
 | 
 | ||||||
|     // dood extractors |     // dood extractors | ||||||
|     DoodToExtractor(), |     DoodToExtractor(), | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue