mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	added extractors (#86)
This commit is contained in:
		
							parent
							
								
									abc9421fb1
								
							
						
					
					
						commit
						ae137f4a34
					
				
					 6 changed files with 195 additions and 20 deletions
				
			
		|  | @ -0,0 +1,37 @@ | |||
| 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.getQualityFromName | ||||
| import com.lagradost.cloudstream3.utils.httpsify | ||||
| 
 | ||||
| class Embedgram : ExtractorApi() { | ||||
|     override val name = "Embedgram" | ||||
|     override val mainUrl = "https://embedgram.com" | ||||
|     override val requiresReferer = true | ||||
| 
 | ||||
|     override suspend fun getUrl( | ||||
|         url: String, | ||||
|         referer: String?, | ||||
|         subtitleCallback: (SubtitleFile) -> Unit, | ||||
|         callback: (ExtractorLink) -> Unit | ||||
|     ) { | ||||
|         val document = app.get(url, referer = referer).document | ||||
|         val link = document.select("video source:last-child").attr("src") | ||||
|         val quality = document.select("video source:last-child").attr("title") | ||||
|         callback.invoke( | ||||
|             ExtractorLink( | ||||
|                 this.name, | ||||
|                 this.name, | ||||
|                 httpsify(link), | ||||
|                 "$mainUrl/", | ||||
|                 getQualityFromName(quality), | ||||
|                 headers = mapOf( | ||||
|                     "Range" to "bytes=0-" | ||||
|                 ) | ||||
|             ) | ||||
|         ) | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,47 @@ | |||
| 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.Qualities | ||||
| 
 | ||||
| class Mvidoo : ExtractorApi() { | ||||
|     override val name = "Mvidoo" | ||||
|     override val mainUrl = "https://mvidoo.com" | ||||
|     override val requiresReferer = true | ||||
| 
 | ||||
|     private fun String.decodeHex(): String { | ||||
|         require(length % 2 == 0) { "Must have an even length" } | ||||
|         return String( | ||||
|             chunked(2) | ||||
|                 .map { it.toInt(16).toByte() } | ||||
|                 .toByteArray() | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun getUrl( | ||||
|         url: String, | ||||
|         referer: String?, | ||||
|         subtitleCallback: (SubtitleFile) -> Unit, | ||||
|         callback: (ExtractorLink) -> Unit | ||||
|     ) { | ||||
|         val document = app.get(url, referer = referer).text | ||||
|         val data = Regex("""\{var\s*[^\s]+\s*=\s*(\[[^]]+])""").find(document)?.groupValues?.get(1) | ||||
|             ?.removeSurrounding("[", "]")?.replace("\"", "")?.replace("\\x", "")?.split(",")?.map { it.decodeHex() }?.reversed()?.joinToString("") ?: return | ||||
|         Regex("source\\s*src=\"([^\"]+)").find(data)?.groupValues?.get(1)?.let { link -> | ||||
|             callback.invoke( | ||||
|                 ExtractorLink( | ||||
|                     this.name, | ||||
|                     this.name, | ||||
|                     link, | ||||
|                     "$mainUrl/", | ||||
|                     Qualities.Unknown.value, | ||||
|                     headers = mapOf( | ||||
|                         "Range" to "bytes=0-" | ||||
|                     ) | ||||
|                 ) | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,81 @@ | |||
| package com.lagradost.cloudstream3.extractors | ||||
| 
 | ||||
| import com.fasterxml.jackson.annotation.JsonProperty | ||||
| import com.lagradost.cloudstream3.APIHolder.getCaptchaToken | ||||
| import com.lagradost.cloudstream3.ErrorLoadingException | ||||
| import com.lagradost.cloudstream3.SubtitleFile | ||||
| import com.lagradost.cloudstream3.app | ||||
| import com.lagradost.cloudstream3.utils.* | ||||
| import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson | ||||
| import java.net.URI | ||||
| 
 | ||||
| class Streamplay : ExtractorApi() { | ||||
|     override val name = "Streamplay" | ||||
|     override val mainUrl = "https://streamplay.to" | ||||
|     override val requiresReferer = true | ||||
| 
 | ||||
|     override suspend fun getUrl( | ||||
|         url: String, | ||||
|         referer: String?, | ||||
|         subtitleCallback: (SubtitleFile) -> Unit, | ||||
|         callback: (ExtractorLink) -> Unit | ||||
|     ) { | ||||
|         val request = app.get(url, referer = referer) | ||||
|         val redirectUrl = request.url | ||||
|         val mainServer = URI(redirectUrl).let { | ||||
|             "${it.scheme}://${it.host}" | ||||
|         } | ||||
|         val key = redirectUrl.substringAfter("embed-").substringBefore(".html") | ||||
|         val token = | ||||
|             request.document.select("script").find { it.data().contains("sitekey:") }?.data() | ||||
|                 ?.substringAfterLast("sitekey: '")?.substringBefore("',")?.let { captchaKey -> | ||||
|                     getCaptchaToken( | ||||
|                         redirectUrl, | ||||
|                         captchaKey, | ||||
|                         referer = "$mainServer/" | ||||
|                     ) | ||||
|                 } ?: throw ErrorLoadingException("can't bypass captcha") | ||||
|         app.post( | ||||
|             "$mainServer/player-$key-488x286.html", data = mapOf( | ||||
|                 "op" to "embed", | ||||
|                 "token" to token | ||||
|             ), | ||||
|             referer = redirectUrl, | ||||
|             headers = mapOf( | ||||
|                 "Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", | ||||
|                 "Content-Type" to "application/x-www-form-urlencoded" | ||||
|             ) | ||||
|         ).document.select("script").find { script -> | ||||
|             script.data().contains("eval(function(p,a,c,k,e,d)") | ||||
|         }?.let { | ||||
|             val data = getAndUnpack(it.data()).substringAfter("sources=[").substringBefore(",desc") | ||||
|                 .replace("file", "\"file\"") | ||||
|                 .replace("label", "\"label\"") | ||||
|             tryParseJson<List<Source>>("[$data}]")?.map { res -> | ||||
|                 callback.invoke( | ||||
|                     ExtractorLink( | ||||
|                         this.name, | ||||
|                         this.name, | ||||
|                         res.file ?: return@map null, | ||||
|                         "$mainServer/", | ||||
|                         when (res.label) { | ||||
|                             "HD" -> Qualities.P720.value | ||||
|                             "SD" -> Qualities.P480.value | ||||
|                             else -> Qualities.Unknown.value | ||||
|                         }, | ||||
|                         headers = mapOf( | ||||
|                             "Range" to "bytes=0-" | ||||
|                         ) | ||||
|                     ) | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     data class Source( | ||||
|         @JsonProperty("file") val file: String? = null, | ||||
|         @JsonProperty("label") val label: String? = null, | ||||
|     ) | ||||
| 
 | ||||
| } | ||||
|  | @ -1,19 +1,23 @@ | |||
| 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.Qualities | ||||
| import com.lagradost.cloudstream3.utils.M3u8Helper | ||||
| 
 | ||||
| class UpstreamExtractor: ExtractorApi() { | ||||
|     override val name: String = "Upstream.to" | ||||
| class UpstreamExtractor : ExtractorApi() { | ||||
|     override val name: String = "Upstream" | ||||
|     override val mainUrl: String = "https://upstream.to" | ||||
|     override val requiresReferer = true | ||||
| 
 | ||||
|     override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> { | ||||
|         // WIP: m3u8 link fetched but sometimes not playing | ||||
|     override suspend fun getUrl( | ||||
|         url: String, | ||||
|         referer: String?, | ||||
|         subtitleCallback: (SubtitleFile) -> Unit, | ||||
|         callback: (ExtractorLink) -> Unit | ||||
|     ) { | ||||
|         //Log.i(this.name, "Result => (no extractor) ${url}") | ||||
|         val sources: MutableList<ExtractorLink> = mutableListOf() | ||||
|         val doc = app.get(url, referer = referer).text | ||||
|         if (doc.isNotBlank()) { | ||||
|             var reg = Regex("(?<=master)(.*)(?=hls)") | ||||
|  | @ -30,7 +34,9 @@ class UpstreamExtractor: ExtractorApi() { | |||
|                             domName = "${part}.${domName}" | ||||
|                         } | ||||
|                         domName.trimEnd('.') | ||||
|                     } else { "" } | ||||
|                     } else { | ||||
|                         "" | ||||
|                     } | ||||
|                 } | ||||
|                 false -> "" | ||||
|             } | ||||
|  | @ -42,18 +48,13 @@ class UpstreamExtractor: ExtractorApi() { | |||
| 
 | ||||
|             result?.forEach { | ||||
|                 val linkUrl = "https://${domain}/hls/${it}/master.m3u8" | ||||
|                 sources.add( | ||||
|                     ExtractorLink( | ||||
|                     name = "Upstream m3u8", | ||||
|                     source = this.name, | ||||
|                     url = linkUrl, | ||||
|                     quality = Qualities.Unknown.value, | ||||
|                     referer = referer ?: linkUrl, | ||||
|                     isM3u8 = true | ||||
|                     ) | ||||
|                 ) | ||||
|                 M3u8Helper.generateM3u8( | ||||
|                     this.name, | ||||
|                     linkUrl, | ||||
|                     "$mainUrl/", | ||||
|                     headers = mapOf("Origin" to mainUrl) | ||||
|                 ).forEach(callback) | ||||
|             } | ||||
|         } | ||||
|         return sources | ||||
|     } | ||||
| } | ||||
|  | @ -7,6 +7,11 @@ import com.lagradost.cloudstream3.utils.ExtractorApi | |||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.getQualityFromName | ||||
| 
 | ||||
| class FEnet: XStreamCdn() { | ||||
|     override val name: String = "FEnet" | ||||
|     override val mainUrl: String = "https://fembed.net" | ||||
| } | ||||
| 
 | ||||
| class Rasacintaku: XStreamCdn() { | ||||
|     override val mainUrl: String = "https://rasa-cintaku-semakin-berantai.xyz" | ||||
| } | ||||
|  |  | |||
|  | @ -238,7 +238,7 @@ val extractorApis: MutableList<ExtractorApi> = arrayListOf( | |||
|     Vidgomunime(), | ||||
| 
 | ||||
|     Fastream(), | ||||
|      | ||||
| 
 | ||||
|     FEmbed(), | ||||
|     FeHD(), | ||||
|     Fplayer(), | ||||
|  | @ -246,13 +246,14 @@ val extractorApis: MutableList<ExtractorApi> = arrayListOf( | |||
|     Luxubu(), | ||||
|     LayarKaca(), | ||||
|     Rasacintaku(), | ||||
|     FEnet(), | ||||
|     //  WatchSB(), 'cause StreamSB.kt works | ||||
|     Uqload(), | ||||
|     Uqload1(), | ||||
|     Evoload(), | ||||
|     Evoload1(), | ||||
|     VoeExtractor(), | ||||
|     // UpstreamExtractor(), GenericM3U8.kt works | ||||
|     UpstreamExtractor(), | ||||
| 
 | ||||
|     Tomatomatela(), | ||||
|     Cinestart(), | ||||
|  | @ -316,6 +317,9 @@ val extractorApis: MutableList<ExtractorApi> = arrayListOf( | |||
|     Acefile(), | ||||
|     SpeedoStream(), | ||||
|     Zorofile(), | ||||
|     Embedgram(), | ||||
|     Mvidoo(), | ||||
|     Streamplay(), | ||||
| 
 | ||||
|     YoutubeExtractor(), | ||||
|     YoutubeShortLinkExtractor(), | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue