diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/GogoanimeProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/GogoanimeProvider.kt index 3c5809ba..2bfd28a6 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/GogoanimeProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/GogoanimeProvider.kt @@ -305,7 +305,7 @@ class GogoanimeProvider : MainAPI() { this.name, "${this.name} ${source.label?.replace("0 P", "0p") ?: ""}", source.file, - "", + "https://gogoplay.io", getQualityFromName(source.label ?: ""), isM3u8 = source.type == "hls" ) diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/GenericM3U8.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/GenericM3U8.kt new file mode 100644 index 00000000..c798a3fa --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/GenericM3U8.kt @@ -0,0 +1,49 @@ +package com.lagradost.cloudstream3.extractors + +import com.lagradost.cloudstream3.apmap +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 ZplayerV2 : GenericM3U8() { + override val name = "Zplayer V2" + override val mainUrl = "https://v2.zplayer.live" +} + +open class GenericM3U8 : ExtractorApi() { + override val name = "Upstream" + override val mainUrl = "https://upstream.to" + override val requiresReferer = false + + override suspend fun getUrl(url: String, referer: String?): List { + val response = app.get( + url, interceptor = WebViewResolver( + Regex("""master\.m3u8""") + ) + ) + val sources = mutableListOf() + if (response.url.contains("m3u8")) M3u8Helper().m3u8Generation( + M3u8Helper.M3u8Stream( + response.url, + headers = response.headers.toMap() + ), true + ) + .map { stream -> + val qualityString = if ((stream.quality ?: 0) == 0) "" else "${stream.quality}p" + sources.add( ExtractorLink( + name, + "$name $qualityString", + stream.streamUrl, + url, + getQualityFromName(stream.quality.toString()), + true + )) + } + return sources + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/Jawcloud.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/Jawcloud.kt new file mode 100644 index 00000000..136e78d5 --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/Jawcloud.kt @@ -0,0 +1,36 @@ +package com.lagradost.cloudstream3.extractors + +import com.lagradost.cloudstream3.apmap +import com.lagradost.cloudstream3.utils.* +import com.lagradost.cloudstream3.app + + +open class Jawcloud : ExtractorApi() { + override val name = "Jawcloud" + override val mainUrl = "https://jawcloud.co" + override val requiresReferer = false + + override suspend fun getUrl(url: String, referer: String?): List? { + val doc = app.get(url).document + val urlString = doc.select("html body div source").attr("src") + val sources = mutableListOf() + if (urlString.contains("m3u8")) M3u8Helper().m3u8Generation( + M3u8Helper.M3u8Stream( + urlString, + headers = app.get(url).headers.toMap() + ), true + ) + .map { stream -> + val qualityString = if ((stream.quality ?: 0) == 0) "" else "${stream.quality}p" + sources.add( ExtractorLink( + name, + "$name $qualityString", + stream.streamUrl, + url, + getQualityFromName(stream.quality.toString()), + true + )) + } + return sources + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/SBPlay.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/SBPlay.kt index a6156a86..3468cbca 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/extractors/SBPlay.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/SBPlay.kt @@ -9,17 +9,13 @@ import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.getPostForm import org.jsoup.Jsoup -class SBPlay1 : SBPlay() { - override val mainUrl = "https://sbplay1.com" -} +//class SBPlay1 : SBPlay() { +// override val mainUrl = "https://sbplay1.com" +//} -class SBPlay2 : SBPlay() { - override val mainUrl = "https://sbplay2.com" -} - -class SBPlay3 : SBPlay() { - override val mainUrl = "https://pelistop.co" -} +//class SBPlay2 : SBPlay() { +// override val mainUrl = "https://sbplay2.com" +//} open class SBPlay : ExtractorApi() { override val mainUrl = "https://sbplay.one" diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/StreamSB.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/StreamSB.kt index 302eba53..73e1932d 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/extractors/StreamSB.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/StreamSB.kt @@ -1,52 +1,142 @@ package com.lagradost.cloudstream3.extractors +import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.cloudstream3.USER_AGENT +import com.lagradost.cloudstream3.apmap +import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.app -import com.lagradost.cloudstream3.utils.ExtractorApi -import com.lagradost.cloudstream3.utils.ExtractorLink -import com.lagradost.cloudstream3.utils.getAndUnpack -import com.lagradost.cloudstream3.utils.getQualityFromName +import com.lagradost.cloudstream3.utils.AppUtils.parseJson -class StreamSB : ExtractorApi() { - override val name = "StreamSB" + +class StreamSB1 : StreamSB() { + override val mainUrl = "https://sbplay1.com" +} + +class StreamSB2 : StreamSB() { + override val mainUrl = "https://sbplay2.com" +} + +class StreamSB3 : StreamSB() { + override val mainUrl = "https://sbplay.one" +} + +class StreamSB4 : StreamSB() { + override val mainUrl = "https://cloudemb.com" +} + +class StreamSB5 : StreamSB() { override val mainUrl = "https://sbplay.org" - private val sourceRegex = Regex("""sources:[\W\w]*?file:\s*"(.*?)"""") +} - //private val m3u8Regex = Regex(""".*?(\d*).m3u8""") - //private val urlRegex = Regex("""(.*?)([^/]+$)""") +class StreamSB6 : StreamSB() { + override val mainUrl = "https://embedsb.com" +} - // 1: Resolution 2: url - private val m3u8UrlRegex = Regex("""RESOLUTION=\d*x(\d*).*\n(http.*.m3u8)""") +class StreamSB7 : StreamSB() { + override val mainUrl = "https://pelistop.co" +} + +class StreamSB8 : StreamSB() { + override val mainUrl = "https://streamsb.net" +} + +class StreamSB9 : StreamSB() { + override val mainUrl = "https://sbplay.one" +} + +// This is a modified version of https://github.com/jmir1/aniyomi-extensions/blob/master/src/en/genoanime/src/eu/kanade/tachiyomi/animeextension/en/genoanime/extractors/StreamSBExtractor.kt +// The following code is under the Apache License 2.0 https://github.com/jmir1/aniyomi-extensions/blob/master/LICENSE +open class StreamSB : ExtractorApi() { + override val name = "StreamSB" + override val mainUrl = "https://watchsb.com" override val requiresReferer = false - // https://sbembed.com/embed-ns50b0cukf9j.html -> https://sbvideo.net/play/ns50b0cukf9j - override suspend fun getUrl(url: String, referer: String?): List { - val extractedLinksList: MutableList = mutableListOf() - val newUrl = url.replace("sbplay.org/embed-", "sbplay.org/play/").removeSuffix(".html") - with(app.get(newUrl, timeout = 10)) { - getAndUnpack(this.text).let { - sourceRegex.findAll(it).forEach { sourceMatch -> - val extractedUrl = sourceMatch.groupValues[1] - if (extractedUrl.contains(".m3u8")) { - with(app.get(extractedUrl)) { - m3u8UrlRegex.findAll(this.text).forEach { match -> - val extractedUrlM3u8 = match.groupValues[2] - val extractedRes = match.groupValues[1] - extractedLinksList.add( - ExtractorLink( - name, - "$name ${extractedRes}p", - extractedUrlM3u8, - extractedUrl, - getQualityFromName(extractedRes), - true - ) - ) - } - } - } - } - } + private val hexArray = "0123456789ABCDEF".toCharArray() + + private fun bytesToHex(bytes: ByteArray): String { + val hexChars = CharArray(bytes.size * 2) + for (j in bytes.indices) { + val v = bytes[j].toInt() and 0xFF + + hexChars[j * 2] = hexArray[v ushr 4] + hexChars[j * 2 + 1] = hexArray[v and 0x0F] } - return extractedLinksList + return String(hexChars) } -} \ No newline at end of file + + + data class StreamData ( + @JsonProperty("file") val file: String, + @JsonProperty("cdn_img") val cdnImg: String, + @JsonProperty("hash") val hash: String, + @JsonProperty("subs") val subs: List, + @JsonProperty("length") val length: String, + @JsonProperty("id") val id: String, + @JsonProperty("title") val title: String, + @JsonProperty("backup") val backup: String, + ) + + data class Main ( + @JsonProperty("stream_data") val streamData: StreamData, + @JsonProperty("status_code") val statusCode: Int, + ) + + override suspend fun getUrl(url: String, referer: String?): List? { + val regexID = Regex("(embed-[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+|\\/e\\/[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)") + val id = regexID.findAll(url).map { + it.value.replace(Regex("(embed-|\\/e\\/)"),"") + }.first() + val bytes = id.toByteArray() + val bytesToHex = bytesToHex(bytes) + val master = "$mainUrl/sources40/566d337678566f743674494a7c7c${bytesToHex}7c7c346b6767586d6934774855537c7c73747265616d7362/6565417268755339773461447c7c346133383438333436313335376136323337373433383634376337633465366534393338373136643732373736343735373237613763376334363733353737303533366236333463353333363534366137633763373337343732363536313664373336327c7c6b586c3163614468645a47617c7c73747265616d7362" + val headers = mapOf( + "Host" to url.substringAfter("https://").substringBefore("/"), + "User-Agent" to USER_AGENT, + "Accept" to "application/json, text/plain, */*", + "Accept-Language" to "en-US,en;q=0.5", + "Referer" to url, + "watchsb" to "streamsb", + "DNT" to "1", + "Connection" to "keep-alive", + "Sec-Fetch-Dest" to "empty", + "Sec-Fetch-Mode" to "no-cors", + "Sec-Fetch-Site" to "same-origin", + "TE" to "trailers", + "Pragma" to "no-cache", + "Cache-Control" to "no-cache",) + val urltext = app.get(master, + headers = headers, + allowRedirects = false + ).text + val mapped = urltext.let { parseJson
(it) } + if (urltext.contains("m3u8")) return M3u8Helper().m3u8Generation( + M3u8Helper.M3u8Stream( + mapped.streamData.file, + headers = mapOf( + "User-Agent" to USER_AGENT, + "Accept" to "*/*", + "Accept-Language" to "en-US,en;q=0.5", + "Accept-Encoding" to "gzip, deflate, br", + "Origin" to mainUrl, + "DNT" to "1", + "Connection" to "keep-alive", + "Referer" to "$mainUrl/", + "Sec-Fetch-Dest" to "empty", + "Sec-Fetch-Mode" to "cors", + "Sec-Fetch-Site" to "cross-site",), + ), 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 null + } +} diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt index 040bc694..70ed69c4 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt @@ -100,18 +100,27 @@ val extractorApis: Array = arrayOf( Mcloud(), XStreamCdn(), StreamSB(), + StreamSB1(), + StreamSB2(), + StreamSB3(), + StreamSB4(), + StreamSB5(), + StreamSB6(), + StreamSB7(), + StreamSB8(), + StreamSB9(), Streamhub(), FEmbed(), FeHD(), Fplayer(), - WatchSB(), + // WatchSB(), 'cause StreamSB.kt works Uqload(), Uqload1(), Evoload(), Evoload1(), VoeExtractor(), - UpstreamExtractor(), + // UpstreamExtractor(), GenericM3U8.kt works Tomatomatela(), Cinestart(), @@ -125,10 +134,15 @@ val extractorApis: Array = arrayOf( AsianLoad(), - SBPlay(), - SBPlay1(), - SBPlay2(), - SBPlay3(), + ZplayerV2(), + GenericM3U8(), + Jawcloud(), + + // StreamSB.kt works + // SBPlay(), + // SBPlay1(), + // SBPlay2(), + ) fun getExtractorApiFromName(name: String): ExtractorApi {