mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	added sub to streamsb & xtreamCdn (#163)
This commit is contained in:
		
							parent
							
								
									7cbcee4d48
								
							
						
					
					
						commit
						ecd363992c
					
				
					 7 changed files with 159 additions and 40 deletions
				
			
		|  | @ -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<AesData>(Regex("data='(\\S+?)'").first(eval)) ?: return | ||||
|         val data = tryParseJson<AesData>(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<List<Tracks>>("[$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 | ||||
|     ) | ||||
| 
 | ||||
| } | ||||
|  | @ -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" | ||||
|                     ) | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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<Subs>?, | ||||
|         @JsonProperty("subs") val subs: ArrayList<Subs>? = 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, | ||||
|                 ) | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -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) | ||||
|             } | ||||
|  |  | |||
|  | @ -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<ResponseData>? | ||||
|         @JsonProperty("player") val player: Player? = null, | ||||
|         @JsonProperty("data") val data: List<ResponseData>?, | ||||
|         @JsonProperty("captions") val captions: List<Captions?>?, | ||||
|     ) | ||||
| 
 | ||||
|     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<ExtractorLink> { | ||||
|     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<ExtractorLink> = 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<ResponseJson?>(text)?.let { | ||||
|         app.post(newUrl, headers = headers).let { res -> | ||||
|             val sources = tryParseJson<ResponseJson?>(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 | ||||
|     } | ||||
| } | ||||
|  | @ -235,6 +235,7 @@ val extractorApis: MutableList<ExtractorApi> = arrayListOf( | |||
|     Vidgomunime(), | ||||
|     Sbflix(), | ||||
|     Streamsss(), | ||||
|     Sbspeed(), | ||||
| 
 | ||||
|     Fastream(), | ||||
| 
 | ||||
|  | @ -246,6 +247,8 @@ val extractorApis: MutableList<ExtractorApi> = arrayListOf( | |||
|     LayarKaca(), | ||||
|     Rasacintaku(), | ||||
|     FEnet(), | ||||
|     Kotakajair(), | ||||
|     Cdnplayer(), | ||||
|     //  WatchSB(), 'cause StreamSB.kt works | ||||
|     Uqload(), | ||||
|     Uqload1(), | ||||
|  | @ -317,6 +320,7 @@ val extractorApis: MutableList<ExtractorApi> = arrayListOf( | |||
|     Linkbox(), | ||||
|     Acefile(), | ||||
|     SpeedoStream(), | ||||
|     SpeedoStream1(), | ||||
|     Zorofile(), | ||||
|     Embedgram(), | ||||
|     Mvidoo(), | ||||
|  | @ -324,6 +328,7 @@ val extractorApis: MutableList<ExtractorApi> = arrayListOf( | |||
|     Vidmoly(), | ||||
|     Vidmolyme(), | ||||
|     Voe(), | ||||
|     Moviehab(), | ||||
| 
 | ||||
|     Gdriveplayerapi(), | ||||
|     Gdriveplayerapp(), | ||||
|  | @ -336,6 +341,7 @@ val extractorApis: MutableList<ExtractorApi> = arrayListOf( | |||
|     Gdriveplayerco(), | ||||
|     Gdriveplayer(), | ||||
|     DatabaseGdrive(), | ||||
|     DatabaseGdrive2(), | ||||
| 
 | ||||
|     YoutubeExtractor(), | ||||
|     YoutubeShortLinkExtractor(), | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue