sora: fix Jeniusplay

This commit is contained in:
hexated 2023-08-29 20:28:15 +07:00
parent 3b1d788587
commit e8661648da
9 changed files with 224 additions and 342 deletions

View file

@ -1,5 +1,5 @@
// use an integer for version numbers
version = 12
version = 13
cloudstream {

View file

@ -13,13 +13,12 @@ import org.jsoup.nodes.Element
import java.net.URI
class IdlixProvider : MainAPI() {
override var mainUrl = "https://tv.idlixprime.com"
override var mainUrl = "https://tv.idlixplus.net"
private var directUrl = mainUrl
override var name = "Idlix"
override val hasMainPage = true
override var lang = "id"
override val hasDownloadSupport = true
private val session = Session(Requests().baseClient)
override val supportedTypes = setOf(
TvType.Movie,
TvType.TvSeries,
@ -51,9 +50,9 @@ class IdlixProvider : MainAPI() {
val url = request.data.split("?")
val nonPaged = request.name == "Featured" && page <= 1
val req = if (nonPaged) {
session.get(request.data)
app.get(request.data)
} else {
session.get("${url.first()}$page/?${url.lastOrNull()}")
app.get("${url.first()}$page/?${url.lastOrNull()}")
}
mainUrl = getBaseUrl(req.url)
val document = req.document
@ -98,7 +97,7 @@ class IdlixProvider : MainAPI() {
}
override suspend fun search(query: String): List<SearchResponse> {
val req = session.get("$mainUrl/search/$query")
val req = app.get("$mainUrl/search/$query")
mainUrl = getBaseUrl(req.url)
val document = req.document
return document.select("div.result-item").map {
@ -113,7 +112,7 @@ class IdlixProvider : MainAPI() {
}
override suspend fun load(url: String): LoadResponse {
val request = session.get(url)
val request = app.get(url)
directUrl = getBaseUrl(request.url)
val document = request.document
val title =
@ -193,7 +192,7 @@ class IdlixProvider : MainAPI() {
callback: (ExtractorLink) -> Unit
): Boolean {
val document = session.get(data).document
val document = app.get(data).document
val id = document.select("meta#dooplay-ajax-counter").attr("data-postid")
val type = if (data.contains("/movie/")) "movie" else "tv"
@ -201,22 +200,18 @@ class IdlixProvider : MainAPI() {
it.attr("data-nume")
}.apmap { nume ->
safeApiCall {
var source = session.post(
url = "$directUrl/wp-admin/admin-ajax.php",
data = mapOf(
"action" to "doo_player_ajax",
"post" to id,
"nume" to nume,
"type" to type
),
val source = app.get(
url = "$directUrl/wp-json/dooplayer/v2/$id/$type/$nume",
headers = mapOf("X-Requested-With" to "XMLHttpRequest"),
referer = data
).let { tryParseJson<ResponseHash>(it.text) }?.embed_url ?: return@safeApiCall
).let { tryParseJson<ResponseHash>(it.text) } ?: return@safeApiCall
if (source.startsWith("https://uservideo.xyz")) {
source = app.get(source).document.select("iframe").attr("src")
var decrypted = AesHelper.cryptoAESHandler(source.embed_url,source.key.toByteArray(), false)?.fixBloat() ?: return@safeApiCall
if (decrypted.startsWith("https://uservideo.xyz")) {
decrypted = app.get(decrypted).document.select("iframe").attr("src")
}
loadExtractor(source, directUrl, subtitleCallback, callback)
loadExtractor(decrypted, "$directUrl/", subtitleCallback, callback)
}
}
@ -224,9 +219,15 @@ class IdlixProvider : MainAPI() {
return true
}
private fun String.fixBloat() : String {
return this.replace("\"", "").replace("\\", "")
}
data class ResponseHash(
@JsonProperty("embed_url") val embed_url: String,
@JsonProperty("key") val key: String,
@JsonProperty("type") val type: String?,
)
}

View file

@ -0,0 +1,95 @@
package com.hexated
import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.ErrorLoadingException
import com.lagradost.cloudstream3.base64DecodeArray
import com.lagradost.cloudstream3.base64Encode
import com.lagradost.cloudstream3.utils.AppUtils
import java.security.DigestException
import java.security.MessageDigest
import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
object AesHelper {
fun cryptoAESHandler(
data: String,
pass: ByteArray,
encrypt: Boolean = true,
padding: String = "AES/CBC/PKCS5PADDING",
): String? {
val parse = AppUtils.tryParseJson<AesData>(data) ?: return null
val (key, iv) = generateKeyAndIv(pass, parse.s.hexToByteArray()) ?: throw ErrorLoadingException("failed to generate key")
val cipher = Cipher.getInstance(padding)
return if (!encrypt) {
cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv))
String(cipher.doFinal(base64DecodeArray(parse.ct)))
} else {
cipher.init(Cipher.ENCRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv))
base64Encode(cipher.doFinal(parse.ct.toByteArray()))
}
}
// https://stackoverflow.com/a/41434590/8166854
private fun generateKeyAndIv(
password: ByteArray,
salt: ByteArray,
hashAlgorithm: String = "MD5",
keyLength: Int = 32,
ivLength: Int = 16,
iterations: Int = 1
): List<ByteArray>? {
val md = MessageDigest.getInstance(hashAlgorithm)
val digestLength = md.digestLength
val targetKeySize = keyLength + ivLength
val requiredLength = (targetKeySize + digestLength - 1) / digestLength * digestLength
val generatedData = ByteArray(requiredLength)
var generatedLength = 0
try {
md.reset()
while (generatedLength < targetKeySize) {
if (generatedLength > 0)
md.update(
generatedData,
generatedLength - digestLength,
digestLength
)
md.update(password)
md.update(salt, 0, 8)
md.digest(generatedData, generatedLength, digestLength)
for (i in 1 until iterations) {
md.update(generatedData, generatedLength, digestLength)
md.digest(generatedData, generatedLength, digestLength)
}
generatedLength += digestLength
}
return listOf(
generatedData.copyOfRange(0, keyLength),
generatedData.copyOfRange(keyLength, targetKeySize)
)
} catch (e: DigestException) {
return null
}
}
private fun String.hexToByteArray(): ByteArray {
check(length % 2 == 0) { "Must have an even length" }
return chunked(2)
.map { it.toInt(16).toByte() }
.toByteArray()
}
private data class AesData(
@JsonProperty("ct") val ct: String,
@JsonProperty("iv") val iv: String,
@JsonProperty("s") val s: String
)
}