diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/Gdriveplayer.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/Gdriveplayer.kt index dfccc118..df9c74a4 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/extractors/Gdriveplayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/Gdriveplayer.kt @@ -3,6 +3,7 @@ package com.lagradost.cloudstream3.extractors import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.utils.* +import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import org.jsoup.nodes.Element import java.security.DigestException import java.security.MessageDigest @@ -10,43 +11,47 @@ import javax.crypto.Cipher import javax.crypto.spec.IvParameterSpec import javax.crypto.spec.SecretKeySpec +class DatabaseGdrive2 : Gdriveplayer() { + override var mainUrl = "https://databasegdriveplayer.co" +} + class DatabaseGdrive : Gdriveplayer() { override var mainUrl = "https://series.databasegdriveplayer.co" } -class Gdriveplayerapi: Gdriveplayer() { +class Gdriveplayerapi : Gdriveplayer() { override val mainUrl: String = "https://gdriveplayerapi.com" } -class Gdriveplayerapp: Gdriveplayer() { +class Gdriveplayerapp : Gdriveplayer() { override val mainUrl: String = "https://gdriveplayer.app" } -class Gdriveplayerfun: Gdriveplayer() { +class Gdriveplayerfun : Gdriveplayer() { override val mainUrl: String = "https://gdriveplayer.fun" } -class Gdriveplayerio: Gdriveplayer() { +class Gdriveplayerio : Gdriveplayer() { override val mainUrl: String = "https://gdriveplayer.io" } -class Gdriveplayerme: Gdriveplayer() { +class Gdriveplayerme : Gdriveplayer() { override val mainUrl: String = "https://gdriveplayer.me" } -class Gdriveplayerbiz: Gdriveplayer() { +class Gdriveplayerbiz : Gdriveplayer() { override val mainUrl: String = "https://gdriveplayer.biz" } -class Gdriveplayerorg: Gdriveplayer() { +class Gdriveplayerorg : Gdriveplayer() { override val mainUrl: String = "https://gdriveplayer.org" } -class Gdriveplayerus: Gdriveplayer() { +class Gdriveplayerus : Gdriveplayer() { override val mainUrl: String = "https://gdriveplayer.us" } -class Gdriveplayerco: Gdriveplayer() { +class Gdriveplayerco : Gdriveplayer() { override val mainUrl: String = "https://gdriveplayer.co" } @@ -136,6 +141,10 @@ open class Gdriveplayer : ExtractorApi() { return find(str)?.groupValues?.getOrNull(1) } + private fun String.addMarks(str: String): String { + return this.replace(Regex("\"?$str\"?"), "\"$str\"") + } + override suspend fun getUrl( url: String, referer: String?, @@ -145,18 +154,19 @@ open class Gdriveplayer : ExtractorApi() { val document = app.get(url).document val eval = unpackJs(document)?.replace("\\", "") ?: return - val data = AppUtils.tryParseJson(Regex("data='(\\S+?)'").first(eval)) ?: return + val data = tryParseJson(Regex("data='(\\S+?)'").first(eval)) ?: return val password = Regex("null,['|\"](\\w+)['|\"]").first(eval) ?.split(Regex("\\D+")) ?.joinToString("") { Char(it.toInt()).toString() }.let { Regex("var pass = \"(\\S+?)\"").first(it ?: return)?.toByteArray() } ?: throw ErrorLoadingException("can't find password") - val decryptedData = - cryptoAESHandler(data, password, false)?.let { getAndUnpack(it) }?.replace("\\", "") - ?.substringAfter("sources:[")?.substringBefore("],") + val decryptedData = cryptoAESHandler(data, password, false)?.let { getAndUnpack(it) }?.replace("\\", "") - Regex("\"file\":\"(\\S+?)\".*?res=(\\d+)").findAll(decryptedData ?: return).map { + val sourceData = decryptedData?.substringAfter("sources:[")?.substringBefore("],") + val subData = decryptedData?.substringAfter("tracks:[")?.substringBefore("],") + + Regex("\"file\":\"(\\S+?)\".*?res=(\\d+)").findAll(sourceData ?: return).map { it.groupValues[1] to it.groupValues[2] }.toList().distinctBy { it.second }.map { (link, quality) -> callback.invoke( @@ -171,6 +181,17 @@ open class Gdriveplayer : ExtractorApi() { ) } + subData?.addMarks("file")?.addMarks("kind")?.addMarks("label").let { dataSub -> + tryParseJson>("[$dataSub]")?.map { sub -> + subtitleCallback.invoke( + SubtitleFile( + sub.label, + httpsify(sub.file) + ) + ) + } + } + } data class AesData( @@ -179,4 +200,10 @@ open class Gdriveplayer : ExtractorApi() { @JsonProperty("s") val s: String ) + data class Tracks( + @JsonProperty("file") val file: String, + @JsonProperty("kind") val kind: String, + @JsonProperty("label") val label: String + ) + } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/Moviehab.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/Moviehab.kt new file mode 100644 index 00000000..e2eb7bf0 --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/Moviehab.kt @@ -0,0 +1,40 @@ +package com.lagradost.cloudstream3.extractors + +import com.lagradost.cloudstream3.SubtitleFile +import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.utils.ExtractorApi +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.M3u8Helper + +class Moviehab : ExtractorApi() { + override var name = "Moviehab" + override var mainUrl = "https://play.moviehab.com" + override val requiresReferer = false + + override suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val res = app.get(url) + res.document.select("video#player").let { + //should redirect first for making it works + val link = app.get("$mainUrl/${it.select("source").attr("src")}", referer = url).url + M3u8Helper.generateM3u8( + this.name, + link, + url + ).forEach(callback) + + Regex("src[\"|'],\\s[\"|'](\\S+)[\"|']\\)").find(res.text)?.groupValues?.get(1).let {sub -> + subtitleCallback.invoke( + SubtitleFile( + it.select("track").attr("label"), + "$mainUrl/$sub" + ) + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/SpeedoStream.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/SpeedoStream.kt index 6153a7c1..8ef6c463 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/extractors/SpeedoStream.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/SpeedoStream.kt @@ -7,7 +7,11 @@ import com.lagradost.cloudstream3.utils.ExtractorApi import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.M3u8Helper -class SpeedoStream : ExtractorApi() { +class SpeedoStream1 : SpeedoStream() { + override val mainUrl = "https://speedostream.nl" +} + +open class SpeedoStream : ExtractorApi() { override val name = "SpeedoStream" override val mainUrl = "https://speedostream.com" override val requiresReferer = true 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 30a0496d..913b410b 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/extractors/StreamSB.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/StreamSB.kt @@ -7,6 +7,11 @@ import com.lagradost.cloudstream3.utils.ExtractorApi import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.M3u8Helper +class Sbspeed : StreamSB() { + override var name = "Sbspeed" + override var mainUrl = "https://sbspeed.com" +} + class Streamsss : StreamSB() { override var mainUrl = "https://streamsss.net" } @@ -93,15 +98,15 @@ open class StreamSB : ExtractorApi() { } data class Subs ( - @JsonProperty("file") val file: String, - @JsonProperty("label") val label: String, + @JsonProperty("file") val file: String? = null, + @JsonProperty("label") val label: String? = null, ) 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("subs") val subs: ArrayList? = arrayListOf(), @JsonProperty("length") val length: String, @JsonProperty("id") val id: String, @JsonProperty("title") val title: String, @@ -141,5 +146,14 @@ open class StreamSB : ExtractorApi() { url, headers = headers ).forEach(callback) + + mapped.streamData.subs?.map {sub -> + subtitleCallback.invoke( + SubtitleFile( + sub.label.toString(), + sub.file ?: return@map null, + ) + ) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/VidSrcExtractor.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/VidSrcExtractor.kt index 63634704..287fe4d4 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/extractors/VidSrcExtractor.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/VidSrcExtractor.kt @@ -85,18 +85,12 @@ open class VidSrcExtractor : ExtractorApi() { this.name, this.name, srcm3u8, - this.mainUrl, + "https://vidsrc.stream/", Qualities.Unknown.value, extractorData = pass, isM3u8 = true ) ) - -// M3u8Helper.generateM3u8( -// name, -// srcm3u8, -// absoluteUrl -// ).forEach(callback) } else { loadExtractor(linkfixed, url, subtitleCallback, callback) } diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/XStreamCdn.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/XStreamCdn.kt index 9e3585ae..15ff0436 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/extractors/XStreamCdn.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/XStreamCdn.kt @@ -1,12 +1,23 @@ package com.lagradost.cloudstream3.extractors import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.app -import com.lagradost.cloudstream3.utils.AppUtils +import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.ExtractorApi import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.getQualityFromName +class Cdnplayer: XStreamCdn() { + override val name: String = "Cdnplayer" + override val mainUrl: String = "https://cdnplayer.online" +} + +class Kotakajair: XStreamCdn() { + override val name: String = "Kotakajair" + override val mainUrl: String = "https://kotakajair.xyz" +} + class FEnet: XStreamCdn() { override val name: String = "FEnet" override val mainUrl: String = "https://fembed.net" @@ -59,44 +70,67 @@ open class XStreamCdn : ExtractorApi() { //val type: String // Mp4 ) + private data class Player( + @JsonProperty("poster_file") val poster_file: String? = null, + ) + private data class ResponseJson( @JsonProperty("success") val success: Boolean, - @JsonProperty("data") val data: List? + @JsonProperty("player") val player: Player? = null, + @JsonProperty("data") val data: List?, + @JsonProperty("captions") val captions: List?, + ) + + private data class Captions( + @JsonProperty("id") val id: String, + @JsonProperty("hash") val hash: String, + @JsonProperty("language") val language: String, + @JsonProperty("extension") val extension: String ) override fun getExtractorUrl(id: String): String { return "$domainUrl/api/source/$id" } - override suspend fun getUrl(url: String, referer: String?): List { + override suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { val headers = mapOf( "Referer" to url, "User-Agent" to "Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.0", ) val id = url.trimEnd('/').split("/").last() val newUrl = "https://${domainUrl}/api/source/${id}" - val extractedLinksList: MutableList = mutableListOf() - with(app.post(newUrl, headers = headers)) { - if (this.code != 200) return listOf() - val text = this.text - if (text.isEmpty()) return listOf() - if (text == """{"success":false,"data":"Video not found or has been removed"}""") return listOf() - AppUtils.parseJson(text)?.let { + app.post(newUrl, headers = headers).let { res -> + val sources = tryParseJson(res.text) + sources?.let { if (it.success && it.data != null) { - it.data.forEach { data -> - extractedLinksList.add( + it.data.map { source -> + callback.invoke( ExtractorLink( name, name = name, - data.file, + source.file, url, - getQualityFromName(data.label), + getQualityFromName(source.label), ) ) } } } + + val userData = sources?.player?.poster_file?.split("/")?.get(2) + sources?.captions?.map { + subtitleCallback.invoke( + SubtitleFile( + it?.language.toString(), + "$mainUrl/asset/userdata/$userData/caption/${it?.hash}/${it?.id}.${it?.extension}" + ) + ) + } } - return extractedLinksList } } \ No newline at end of file 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 8d6b1b82..ca612385 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt @@ -235,6 +235,7 @@ val extractorApis: MutableList = arrayListOf( Vidgomunime(), Sbflix(), Streamsss(), + Sbspeed(), Fastream(), @@ -246,6 +247,8 @@ val extractorApis: MutableList = arrayListOf( LayarKaca(), Rasacintaku(), FEnet(), + Kotakajair(), + Cdnplayer(), // WatchSB(), 'cause StreamSB.kt works Uqload(), Uqload1(), @@ -317,6 +320,7 @@ val extractorApis: MutableList = arrayListOf( Linkbox(), Acefile(), SpeedoStream(), + SpeedoStream1(), Zorofile(), Embedgram(), Mvidoo(), @@ -324,6 +328,7 @@ val extractorApis: MutableList = arrayListOf( Vidmoly(), Vidmolyme(), Voe(), + Moviehab(), Gdriveplayerapi(), Gdriveplayerapp(), @@ -336,6 +341,7 @@ val extractorApis: MutableList = arrayListOf( Gdriveplayerco(), Gdriveplayer(), DatabaseGdrive(), + DatabaseGdrive2(), YoutubeExtractor(), YoutubeShortLinkExtractor(),