extractor: added vidplay and fix few extractors (#795)

* extractor: added Vidplay

* fix id

* fix Chillx

* fix Linkbox

* update m3u8helper in chillx

* fix Dailymotion

---------

Co-authored-by: Sofie99 <Sofie99@gmail.com>
This commit is contained in:
Sofie 2023-12-08 23:28:16 +07:00 committed by GitHub
parent dfd6ce7651
commit 6f3a8c1cd2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 120 additions and 30 deletions

View file

@ -7,7 +7,7 @@ import com.lagradost.cloudstream3.extractors.helper.AesHelper.cryptoAESHandler
import com.lagradost.cloudstream3.utils.AppUtils import com.lagradost.cloudstream3.utils.AppUtils
import com.lagradost.cloudstream3.utils.ExtractorApi import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.M3u8Helper
class Moviesapi : Chillx() { class Moviesapi : Chillx() {
override val name = "Moviesapi" override val name = "Moviesapi"
@ -23,13 +23,14 @@ class Watchx : Chillx() {
override val name = "Watchx" override val name = "Watchx"
override val mainUrl = "https://watchx.top" override val mainUrl = "https://watchx.top"
} }
open class Chillx : ExtractorApi() { open class Chillx : ExtractorApi() {
override val name = "Chillx" override val name = "Chillx"
override val mainUrl = "https://chillx.top" override val mainUrl = "https://chillx.top"
override val requiresReferer = true override val requiresReferer = true
companion object { companion object {
private const val KEY = "eN0^>\$^#M08uFv%c" private const val KEY = "tSIsE8FgpRkv3QQQ"
} }
override suspend fun getUrl( override suspend fun getUrl(
@ -38,10 +39,14 @@ open class Chillx : ExtractorApi() {
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
) { ) {
val master = Regex("MasterJS\\s*=\\s*'([^']+)").find( val master = Regex("\\s*=\\s*'([^']+)").find(
app.get( app.get(
url, url,
referer = referer referer = referer ?: "",
headers = mapOf(
"Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Accept-Language" to "en-US,en;q=0.5",
)
).text ).text
)?.groupValues?.get(1) )?.groupValues?.get(1)
val decrypt = cryptoAESHandler(master ?: return, KEY.toByteArray(), false)?.replace("\\", "") ?: throw ErrorLoadingException("failed to decrypt") val decrypt = cryptoAESHandler(master ?: return, KEY.toByteArray(), false)?.replace("\\", "") ?: throw ErrorLoadingException("failed to decrypt")
@ -59,17 +64,12 @@ open class Chillx : ExtractorApi() {
"Origin" to mainUrl, "Origin" to mainUrl,
) )
callback.invoke( M3u8Helper.generateM3u8(
ExtractorLink( name,
name, source ?: return,
name, "$mainUrl/",
source ?: return, headers = headers
"$mainUrl/", ).forEach(callback)
Qualities.P1080.value,
headers = headers,
isM3u8 = true
)
)
AppUtils.tryParseJson<List<Tracks>>("[$tracks]") AppUtils.tryParseJson<List<Tracks>>("[$tracks]")
?.filter { it.kind == "captions" }?.map { track -> ?.filter { it.kind == "captions" }?.map { track ->

View file

@ -7,7 +7,6 @@ import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
import com.lagradost.cloudstream3.utils.ExtractorApi import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.M3u8Helper.Companion.generateM3u8 import com.lagradost.cloudstream3.utils.M3u8Helper.Companion.generateM3u8
import com.lagradost.cloudstream3.utils.Qualities
import java.net.URL import java.net.URL
open class Dailymotion : ExtractorApi() { open class Dailymotion : ExtractorApi() {
@ -27,21 +26,16 @@ open class Dailymotion : ExtractorApi() {
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
) { ) {
val embedUrl = getEmbedUrl(url) ?: return val embedUrl = getEmbedUrl(url) ?: return
val doc = app.get(embedUrl).document val req = app.get(embedUrl)
val prefix = "window.__PLAYER_CONFIG__ = " val prefix = "window.__PLAYER_CONFIG__ = "
val configStr = doc.selectFirst("script:containsData($prefix)")?.data() ?: return val configStr = req.document.selectFirst("script:containsData($prefix)")?.data() ?: return
val config = tryParseJson<Config>(configStr.substringAfter(prefix)) ?: return val config = tryParseJson<Config>(configStr.substringAfter(prefix).substringBefore(";").trim()) ?: return
val id = getVideoId(embedUrl) ?: return val id = getVideoId(embedUrl) ?: return
val dmV1st = config.dmInternalData.v1st val dmV1st = config.dmInternalData.v1st
val dmTs = config.dmInternalData.ts val dmTs = config.dmInternalData.ts
val metaDataUrl = val embedder = config.context.embedder
"$mainUrl/player/metadata/video/$id?locale=en&dmV1st=$dmV1st&dmTs=$dmTs&is_native_app=0" val metaDataUrl = "$mainUrl/player/metadata/video/$id?embedder=$embedder&locale=en-US&dmV1st=$dmV1st&dmTs=$dmTs&is_native_app=0"
val cookies = mapOf( val metaData = app.get(metaDataUrl, referer = embedUrl, cookies = req.cookies)
"v1st" to dmV1st,
"dmvk" to config.context.dmvk,
"ts" to dmTs.toString()
)
val metaData = app.get(metaDataUrl, referer = embedUrl, cookies = cookies)
.parsedSafe<MetaData>() ?: return .parsedSafe<MetaData>() ?: return
metaData.qualities.forEach { (_, video) -> metaData.qualities.forEach { (_, video) ->
video.forEach { video.forEach {
@ -84,13 +78,13 @@ open class Dailymotion : ExtractorApi() {
) )
data class InternalData( data class InternalData(
val ts: Int, val ts: Long,
val v1st: String val v1st: String
) )
data class Context( data class Context(
@JsonProperty("access_token") val accessToken: String?, @JsonProperty("access_token") val accessToken: String?,
val dmvk: String, val embedder: String?,
) )
data class MetaData( data class MetaData(

View file

@ -18,7 +18,8 @@ open class Linkbox : ExtractorApi() {
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
) { ) {
val id = Regex("""(?:/f/|/file/|\?id=)(\w+)""").find(url)?.groupValues?.get(1) val token = Regex("""(?:/f/|/file/|\?id=)(\w+)""").find(url)?.groupValues?.get(1)
val id = app.get("$mainUrl/api/file/share_out_list/?sortField=utime&sortAsc=0&pageNo=1&pageSize=50&shareToken=$token").parsedSafe<Responses>()?.data?.itemId
app.get("$mainUrl/api/file/detail?itemId=$id", referer = url) app.get("$mainUrl/api/file/detail?itemId=$id", referer = url)
.parsedSafe<Responses>()?.data?.itemInfo?.resolutionList?.map { link -> .parsedSafe<Responses>()?.data?.itemInfo?.resolutionList?.map { link ->
callback.invoke( callback.invoke(
@ -44,6 +45,7 @@ open class Linkbox : ExtractorApi() {
data class Data( data class Data(
@JsonProperty("itemInfo") val itemInfo: ItemInfo? = null, @JsonProperty("itemInfo") val itemInfo: ItemInfo? = null,
@JsonProperty("itemId") val itemId: String? = null,
) )
data class Responses( data class Responses(

View file

@ -0,0 +1,92 @@
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.base64Encode
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.M3u8Helper
import javax.crypto.Cipher
import javax.crypto.spec.SecretKeySpec
// Code found in https://github.com/Claudemirovsky/worstsource-keys
// special credits to @Claudemirovsky for providing key
open class Vidplay : ExtractorApi() {
override val name = "Vidplay"
override val mainUrl = "https://vidplay.site"
override val requiresReferer = true
override suspend fun getUrl(
url: String,
referer: String?,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
) {
val id = url.substringBefore("?").substringAfterLast("/")
val encodeId = encodeId(id, getKeys())
val mediaUrl = callFutoken(encodeId, url)
val res = app.get(
"$mediaUrl", headers = mapOf(
"Accept" to "application/json, text/javascript, */*; q=0.01",
"X-Requested-With" to "XMLHttpRequest",
), referer = url
).parsedSafe<Response>()?.result?.sources
res?.map {
M3u8Helper.generateM3u8(
this.name,
it.file ?: return@map,
"$mainUrl/"
).forEach(callback)
}
}
private suspend fun getKeys(): List<String> {
return app.get("https://raw.githubusercontent.com/Claudemirovsky/worstsource-keys/keys/keys.json")
.parsed()
}
private suspend fun callFutoken(id: String, url: String): String? {
val script = app.get("$mainUrl/futoken").text
val k = "k='(\\S+)'".toRegex().find(script)?.groupValues?.get(1) ?: return null
val a = mutableListOf(k)
for (i in id.indices) {
a.add((k[i % k.length].code + id[i].code).toString())
}
return "$mainUrl/mediainfo/${a.joinToString(",")}?${url.substringAfter("?")}"
}
private fun encodeId(id: String, keyList: List<String>): String {
val cipher1 = Cipher.getInstance("RC4")
val cipher2 = Cipher.getInstance("RC4")
cipher1.init(
Cipher.DECRYPT_MODE,
SecretKeySpec(keyList[0].toByteArray(), "RC4"),
cipher1.parameters
)
cipher2.init(
Cipher.DECRYPT_MODE,
SecretKeySpec(keyList[1].toByteArray(), "RC4"),
cipher2.parameters
)
var input = id.toByteArray()
input = cipher1.doFinal(input)
input = cipher2.doFinal(input)
return base64Encode(input).replace("/", "_")
}
data class Sources(
@JsonProperty("file") val file: String? = null,
)
data class Result(
@JsonProperty("sources") val sources: ArrayList<Sources>? = arrayListOf(),
)
data class Response(
@JsonProperty("result") val result: Result? = null,
)
}

View file

@ -167,6 +167,7 @@ import com.lagradost.cloudstream3.extractors.Vidgomunimesb
import com.lagradost.cloudstream3.extractors.Vidmoly import com.lagradost.cloudstream3.extractors.Vidmoly
import com.lagradost.cloudstream3.extractors.Vidmolyme import com.lagradost.cloudstream3.extractors.Vidmolyme
import com.lagradost.cloudstream3.extractors.Vido import com.lagradost.cloudstream3.extractors.Vido
import com.lagradost.cloudstream3.extractors.Vidplay
import com.lagradost.cloudstream3.extractors.Vidstreamz import com.lagradost.cloudstream3.extractors.Vidstreamz
import com.lagradost.cloudstream3.extractors.Vizcloud import com.lagradost.cloudstream3.extractors.Vizcloud
import com.lagradost.cloudstream3.extractors.Vizcloud2 import com.lagradost.cloudstream3.extractors.Vizcloud2
@ -793,6 +794,7 @@ val extractorApis: MutableList<ExtractorApi> = arrayListOf(
VidSrcExtractor2(), VidSrcExtractor2(),
PlayLtXyz(), PlayLtXyz(),
AStreamHub(), AStreamHub(),
Vidplay(),
Cda(), Cda(),
Dailymotion(), Dailymotion(),