massively improved zoro

This commit is contained in:
Blatzar 2021-12-12 02:49:41 +01:00
parent 4b0a3e0c4e
commit 2a55a256aa
5 changed files with 105 additions and 53 deletions

View file

@ -8,6 +8,7 @@ import com.lagradost.cloudstream3.movieproviders.SflixProvider.Companion.toExtra
import com.lagradost.cloudstream3.movieproviders.SflixProvider.Companion.toSubtitleFile
import com.lagradost.cloudstream3.network.WebViewResolver
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.loadExtractor
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
import java.net.URI
@ -152,7 +153,8 @@ class ZoroProvider : MainAPI() {
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"))
AnimeSearchResponse(
@ -187,7 +189,8 @@ class ZoroProvider : MainAPI() {
when {
(year != null && japaneseTitle != null && status != null) -> break
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 ->
japaneseTitle = info.selectFirst(".name")?.text().toString()
@ -255,61 +258,59 @@ class ZoroProvider : MainAPI() {
callback: (ExtractorLink) -> Unit
): Boolean {
// Copy pasted from Sflix :)
val servers: List<Pair<DubStatus, String>> = Jsoup.parse(
mapper.readValue<Response>(
app.get("$mainUrl/ajax/v2/episode/servers?episodeId=" + data.split("=")[1]).text
).html
app.get("$mainUrl/ajax/v2/episode/servers?episodeId=" + data.split("=")[1])
.mapped<Response>().html
).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(
it.first,
getM3u8FromRapidCloud(
mapper.readValue<RapidCloudResponse>(
app.get(
link,
res.headers.toMap()
).text
).link
)
if (it.attr("data-type") == "sub") DubStatus.Subbed else DubStatus.Dubbed,
it.attr("data-id")!!
)
}
responses.forEach {
if (it.second.contains("<html")) return@forEach
val mapped = mapper.readValue<SflixProvider.SourceObject>(it.second)
// Prevent duplicates
servers.distinctBy { it.second }.pmap {
val link =
"$mainUrl/ajax/v2/episode/sources?id=${it.second}"
val extractorLink = app.get(
link,
).mapped<RapidCloudResponse>().link
mapped.tracks?.forEach { track ->
track?.toSubtitleFile()?.let { subtitleFile ->
subtitleCallback.invoke(subtitleFile)
// 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 ->
track?.toSubtitleFile()?.let { subtitleFile ->
subtitleCallback.invoke(subtitleFile)
}
}
}
val list = listOf(
mapped.sources to "source 1",
mapped.sources1 to "source 2",
mapped.sources2 to "source 3",
mapped.sourcesBackup to "source backup"
)
val list = listOf(
mapped.sources to "source 1",
mapped.sources1 to "source 2",
mapped.sources2 to "source 3",
mapped.sourcesBackup to "source backup"
)
list.forEach { subList ->
subList.first?.forEach { a ->
a?.toExtractorLink(this, subList.second + " - ${it.first}")?.forEach(callback)
list.forEach { subList ->
subList.first?.forEach { a ->
a?.toExtractorLink(this, subList.second + " - ${it.first}")
?.forEach(callback)
}
}
}
}

View file

@ -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
}
}

View file

@ -9,6 +9,8 @@ import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.mapper
import okhttp3.*
import okhttp3.Headers.Companion.toHeaders
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import java.io.File
import java.net.URI
import java.util.*
@ -78,6 +80,7 @@ class AppResponse(
val body by lazy { response.body }
val code = response.code
val headers = response.headers
val document: Document by lazy { Jsoup.parse(text) }
/** Same as using mapper.readValue<T>() */
inline fun <reified T : Any> mapped(): T {

View file

@ -741,9 +741,7 @@ class PlayerFragment : Fragment() {
}
private fun safeReleasePlayer() {
thread {
simpleCache?.release()
}
simpleCache?.release()
if (this::exoPlayer.isInitialized) {
exoPlayer.release()
}
@ -1928,7 +1926,6 @@ class PlayerFragment : Fragment() {
// torrentStream?.stopStream()
// torrentStream = null
super.onDestroy()
canEnterPipMode = false
savePositionInPlayer()
@ -1938,6 +1935,7 @@ class PlayerFragment : Fragment() {
activity?.showSystemUI()
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER
super.onDestroy()
}
override fun onPause() {

View file

@ -58,13 +58,17 @@ fun getAndUnpack(string: String): 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) {
if (url.startsWith(extractor.mainUrl)) {
extractor.getSafeUrl(url, referer)?.forEach(callback)
return
return true
}
}
return false
}
val extractorApis: Array<ExtractorApi> = arrayOf(
@ -78,6 +82,7 @@ val extractorApis: Array<ExtractorApi> = arrayOf(
Streamhub(),
SBPlay(),
FEmbed(),
WatchSB(),
// dood extractors
DoodToExtractor(),