forked from recloudstream/cloudstream
		
	Extractors (#677)
* StreamSB fix and Jawcloud * Fixes and referer for gogoanime * streamsb fix * Update StreamSB.kt Co-authored-by: Osten <11805592+LagradOst@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									8f9ac96de5
								
							
						
					
					
						commit
						6500d3d897
					
				
					 6 changed files with 243 additions and 58 deletions
				
			
		|  | @ -305,7 +305,7 @@ class GogoanimeProvider : MainAPI() { | ||||||
|                                 this.name, |                                 this.name, | ||||||
|                                 "${this.name} ${source.label?.replace("0 P", "0p") ?: ""}", |                                 "${this.name} ${source.label?.replace("0 P", "0p") ?: ""}", | ||||||
|                                 source.file, |                                 source.file, | ||||||
|                                 "", |                                 "https://gogoplay.io", | ||||||
|                                 getQualityFromName(source.label ?: ""), |                                 getQualityFromName(source.label ?: ""), | ||||||
|                                 isM3u8 = source.type == "hls" |                                 isM3u8 = source.type == "hls" | ||||||
|                             ) |                             ) | ||||||
|  |  | ||||||
|  | @ -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<ExtractorLink> { | ||||||
|  |         val response = app.get( | ||||||
|  |             url, interceptor = WebViewResolver( | ||||||
|  |                 Regex("""master\.m3u8""") | ||||||
|  |             ) | ||||||
|  |         ) | ||||||
|  |         val sources = mutableListOf<ExtractorLink>() | ||||||
|  |         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 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -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<ExtractorLink>? { | ||||||
|  |         val doc = app.get(url).document | ||||||
|  |         val urlString = doc.select("html body div source").attr("src") | ||||||
|  |         val sources = mutableListOf<ExtractorLink>() | ||||||
|  |         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 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -9,17 +9,13 @@ import com.lagradost.cloudstream3.utils.Qualities | ||||||
| import com.lagradost.cloudstream3.utils.getPostForm | import com.lagradost.cloudstream3.utils.getPostForm | ||||||
| import org.jsoup.Jsoup | import org.jsoup.Jsoup | ||||||
| 
 | 
 | ||||||
| class SBPlay1 : SBPlay() { | //class SBPlay1 : SBPlay() { | ||||||
|     override val mainUrl = "https://sbplay1.com" | //    override val mainUrl = "https://sbplay1.com" | ||||||
| } | //} | ||||||
| 
 | 
 | ||||||
| class SBPlay2 : SBPlay() { | //class SBPlay2 : SBPlay() { | ||||||
|     override val mainUrl = "https://sbplay2.com" | //    override val mainUrl = "https://sbplay2.com" | ||||||
| } | //} | ||||||
| 
 |  | ||||||
| class SBPlay3 : SBPlay() { |  | ||||||
|     override val mainUrl = "https://pelistop.co" |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| open class SBPlay : ExtractorApi() { | open class SBPlay : ExtractorApi() { | ||||||
|     override val mainUrl = "https://sbplay.one" |     override val mainUrl = "https://sbplay.one" | ||||||
|  |  | ||||||
|  | @ -1,52 +1,142 @@ | ||||||
| package com.lagradost.cloudstream3.extractors | 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.app | ||||||
| import com.lagradost.cloudstream3.utils.ExtractorApi | import com.lagradost.cloudstream3.utils.AppUtils.parseJson | ||||||
| import com.lagradost.cloudstream3.utils.ExtractorLink |  | ||||||
| import com.lagradost.cloudstream3.utils.getAndUnpack |  | ||||||
| import com.lagradost.cloudstream3.utils.getQualityFromName |  | ||||||
| 
 | 
 | ||||||
| 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" |     override val mainUrl = "https://sbplay.org" | ||||||
|     private val sourceRegex = Regex("""sources:[\W\w]*?file:\s*"(.*?)"""") | } | ||||||
| 
 | 
 | ||||||
|     //private val m3u8Regex = Regex(""".*?(\d*).m3u8""") | class StreamSB6 : StreamSB() { | ||||||
|     //private val urlRegex = Regex("""(.*?)([^/]+$)""") |     override val mainUrl = "https://embedsb.com" | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|     // 1: Resolution 2: url | class StreamSB7 : StreamSB() { | ||||||
|     private val m3u8UrlRegex = Regex("""RESOLUTION=\d*x(\d*).*\n(http.*.m3u8)""") |     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 |     override val requiresReferer = false | ||||||
| 
 | 
 | ||||||
|     // 	https://sbembed.com/embed-ns50b0cukf9j.html   ->   https://sbvideo.net/play/ns50b0cukf9j |     private val hexArray = "0123456789ABCDEF".toCharArray() | ||||||
|     override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> { | 
 | ||||||
|         val extractedLinksList: MutableList<ExtractorLink> = mutableListOf() |     private fun bytesToHex(bytes: ByteArray): String { | ||||||
|         val newUrl = url.replace("sbplay.org/embed-", "sbplay.org/play/").removeSuffix(".html") |         val hexChars = CharArray(bytes.size * 2) | ||||||
|         with(app.get(newUrl, timeout = 10)) { |         for (j in bytes.indices) { | ||||||
|             getAndUnpack(this.text).let { |             val v = bytes[j].toInt() and 0xFF | ||||||
|                 sourceRegex.findAll(it).forEach { sourceMatch -> | 
 | ||||||
|                     val extractedUrl = sourceMatch.groupValues[1] |             hexChars[j * 2] = hexArray[v ushr 4] | ||||||
|                     if (extractedUrl.contains(".m3u8")) { |             hexChars[j * 2 + 1] = hexArray[v and 0x0F] | ||||||
|                         with(app.get(extractedUrl)) { |         } | ||||||
|                             m3u8UrlRegex.findAll(this.text).forEach { match -> |         return String(hexChars) | ||||||
|                                 val extractedUrlM3u8 = match.groupValues[2] |     } | ||||||
|                                 val extractedRes = match.groupValues[1] | 
 | ||||||
|                                 extractedLinksList.add( | 
 | ||||||
|  |     data class StreamData ( | ||||||
|  |         @JsonProperty("file") val file: String, | ||||||
|  |         @JsonProperty("cdn_img") val cdnImg: String, | ||||||
|  |         @JsonProperty("hash") val hash: String, | ||||||
|  |         @JsonProperty("subs") val subs: List<String>, | ||||||
|  |         @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<ExtractorLink>? { | ||||||
|  |         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<Main>(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( |                 ExtractorLink( | ||||||
|                     name, |                     name, | ||||||
|                                         "$name ${extractedRes}p", |                     "$name $qualityString", | ||||||
|                                         extractedUrlM3u8, |                     stream.streamUrl, | ||||||
|                                         extractedUrl, |                     url, | ||||||
|                                         getQualityFromName(extractedRes), |                     getQualityFromName(stream.quality.toString()), | ||||||
|                     true |                     true | ||||||
|                 ) |                 ) | ||||||
|                                 ) |             } | ||||||
|                             } |         return null | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return extractedLinksList |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -100,18 +100,27 @@ val extractorApis: Array<ExtractorApi> = arrayOf( | ||||||
|     Mcloud(), |     Mcloud(), | ||||||
|     XStreamCdn(), |     XStreamCdn(), | ||||||
|     StreamSB(), |     StreamSB(), | ||||||
|  |     StreamSB1(), | ||||||
|  |     StreamSB2(), | ||||||
|  |     StreamSB3(), | ||||||
|  |     StreamSB4(), | ||||||
|  |     StreamSB5(), | ||||||
|  |     StreamSB6(), | ||||||
|  |     StreamSB7(), | ||||||
|  |     StreamSB8(), | ||||||
|  |     StreamSB9(), | ||||||
|     Streamhub(), |     Streamhub(), | ||||||
| 
 | 
 | ||||||
|     FEmbed(), |     FEmbed(), | ||||||
|     FeHD(), |     FeHD(), | ||||||
|     Fplayer(), |     Fplayer(), | ||||||
|     WatchSB(), |   //  WatchSB(), 'cause StreamSB.kt works | ||||||
|     Uqload(), |     Uqload(), | ||||||
|     Uqload1(), |     Uqload1(), | ||||||
|     Evoload(), |     Evoload(), | ||||||
|     Evoload1(), |     Evoload1(), | ||||||
|     VoeExtractor(), |     VoeExtractor(), | ||||||
|     UpstreamExtractor(), |    // UpstreamExtractor(), GenericM3U8.kt works | ||||||
| 
 | 
 | ||||||
|     Tomatomatela(), |     Tomatomatela(), | ||||||
|     Cinestart(), |     Cinestart(), | ||||||
|  | @ -125,10 +134,15 @@ val extractorApis: Array<ExtractorApi> = arrayOf( | ||||||
| 
 | 
 | ||||||
|     AsianLoad(), |     AsianLoad(), | ||||||
| 
 | 
 | ||||||
|     SBPlay(), |     ZplayerV2(), | ||||||
|     SBPlay1(), |     GenericM3U8(), | ||||||
|     SBPlay2(), |     Jawcloud(), | ||||||
|     SBPlay3(), | 
 | ||||||
|  |   // StreamSB.kt works | ||||||
|  |   //  SBPlay(), | ||||||
|  |   //  SBPlay1(), | ||||||
|  |   //  SBPlay2(), | ||||||
|  | 
 | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| fun getExtractorApiFromName(name: String): ExtractorApi { | fun getExtractorApiFromName(name: String): ExtractorApi { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue