VideoVard and WcoHelper changes (#1109)

This commit is contained in:
Stormunblessed 2022-05-30 16:39:26 +00:00 committed by GitHub
parent c67eb095b3
commit 0c6cf7a0b8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 289 additions and 12 deletions

View file

@ -283,7 +283,8 @@ class NineAnimeProvider : MainAPI() {
jsonservers.vidstream, jsonservers.vidstream,
jsonservers.mcloud, jsonservers.mcloud,
jsonservers.mp4upload, jsonservers.mp4upload,
jsonservers.streamtape jsonservers.streamtape,
jsonservers.videovard
).mapNotNull { ).mapNotNull {
try { try {
val epserver = app.get("$mainUrl/ajax/anime/episode?id=$it").text val epserver = app.get("$mainUrl/ajax/anime/episode?id=$it").text

View file

@ -34,8 +34,9 @@ open class Mcloud : ExtractorApi() {
private val key = "LCbu3iYC7ln24K7P" // key credits @Modder4869 private val key = "LCbu3iYC7ln24K7P" // key credits @Modder4869
override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink>? { override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink>? {
val id = url.substringAfter("e/").substringAfter("embed/").substringBefore("?") val id = url.substringAfter("e/").substringAfter("embed/").substringBefore("?")
keytwo = getWcoKey() ?: return null val keys = getWcoKey()
val encryptedid = encrypt(cipher(key, encrypt(id))).replace("/", "_").replace("=","") keytwo = keys?.wcoKey ?: return null
val encryptedid = encrypt(cipher(keys.wcocipher!!, encrypt(id))).replace("/", "_").replace("=","")
val link = "$mainUrl/info/$encryptedid" val link = "$mainUrl/info/$encryptedid"
val response = app.get(link, headers = headers).text val response = app.get(link, headers = headers).text
if(response.startsWith("<!DOCTYPE html>")) { if(response.startsWith("<!DOCTYPE html>")) {

View file

@ -0,0 +1,271 @@
package com.lagradost.cloudstream3.extractors
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.M3u8Helper.Companion.generateM3u8
import kotlinx.coroutines.delay
import java.math.BigInteger
class VideovardSX : WcoStream() {
override var mainUrl = "https://videovard.sx"
}
class VideoVard : ExtractorApi() {
override var name = "Videovard" // Cause works for animekisa and wco
override var mainUrl = "https://videovard.to"
override val requiresReferer = false
//The following code was extracted from https://github.com/saikou-app/saikou/blob/main/app/src/main/java/ani/saikou/parsers/anime/extractors/VideoVard.kt
override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> {
val id = url.substringAfter("e/").substringBefore("/")
val sources = mutableListOf<ExtractorLink>()
val hash = app.get("$mainUrl/api/make/download/$id").parsed<HashResponse>()
delay(11_000)
val resm3u8 = app.post(
"$mainUrl/api/player/setup",
mapOf("Referer" to "$mainUrl/"),
data = mapOf(
"cmd" to "get_stream",
"file_code" to id,
"hash" to hash.hash!!
)
).parsed<SetupResponse>()
val m3u8 = decode(resm3u8.src!!, resm3u8.seed)
sources.addAll(
generateM3u8(
name,
m3u8,
mainUrl,
headers = mapOf("Referer" to mainUrl)
)
)
return sources
}
companion object {
private val big0 = 0.toBigInteger()
private val big3 = 3.toBigInteger()
private val big4 = 4.toBigInteger()
private val big15 = 15.toBigInteger()
private val big16 = 16.toBigInteger()
private val big255 = 255.toBigInteger()
private fun decode(dataFile: String, seed: String): String {
val dataSeed = replace(seed)
val newDataSeed = binaryDigest(dataSeed)
val newDataFile = bytes2blocks(ascii2bytes(dataFile))
var list = listOf(1633837924, 1650680933).map { it.toBigInteger() }
val xorList = mutableListOf<BigInteger>()
for (i in newDataFile.indices step 2) {
val temp = newDataFile.slice(i..i + 1)
xorList += xorBlocks(list, tearDecode(temp, newDataSeed))
list = temp
}
val result = replace(unPad(blocks2bytes(xorList)).map { it.toInt().toChar() }.joinToString(""))
return padLastChars(result)
}
private fun binaryDigest(input: String): List<BigInteger> {
val keys = listOf(1633837924, 1650680933, 1667523942, 1684366951).map { it.toBigInteger() }
var list1 = keys.slice(0..1)
var list2 = list1
val blocks = bytes2blocks(digestPad(input))
for (i in blocks.indices step 4) {
list1 = tearCode(xorBlocks(blocks.slice(i..i + 1), list1), keys).toMutableList()
list2 = tearCode(xorBlocks(blocks.slice(i + 2..i + 3), list2), keys).toMutableList()
val temp = list1[0]
list1[0] = list1[1]
list1[1] = list2[0]
list2[0] = list2[1]
list2[1] = temp
}
return listOf(list1[0], list1[1], list2[0], list2[1])
}
private fun tearDecode(a90: List<BigInteger>, a91: List<BigInteger>): MutableList<BigInteger> {
var (a95, a96) = a90
var a97 = (-957401312).toBigInteger()
for (_i in 0 until 32) {
a96 -= ((((a95 shl 4) xor rShift(a95, 5)) + a95) xor (a97 + a91[rShift(a97, 11).and(3.toBigInteger()).toInt()]))
a97 += 1640531527.toBigInteger()
a95 -= ((((a96 shl 4) xor rShift(a96, 5)) + a96) xor (a97 + a91[a97.and(3.toBigInteger()).toInt()]))
}
return mutableListOf(a95, a96)
}
private fun digestPad(string: String): List<BigInteger> {
val empList = mutableListOf<BigInteger>()
val length = string.length
val extra = big15 - (length.toBigInteger() % big16)
empList.add(extra)
for (i in 0 until length) {
empList.add(string[i].code.toBigInteger())
}
for (i in 0 until extra.toInt()) {
empList.add(big0)
}
return empList
}
private fun bytes2blocks(a22: List<BigInteger>): List<BigInteger> {
val empList = mutableListOf<BigInteger>()
val length = a22.size
var listIndex = 0
for (i in 0 until length) {
val subIndex = i % 4
val shiftedByte = a22[i] shl (3 - subIndex) * 8
if (subIndex == 0) {
empList.add(shiftedByte)
} else {
empList[listIndex] = empList[listIndex] or shiftedByte
}
if (subIndex == 3) listIndex += 1
}
return empList
}
private fun blocks2bytes(inp: List<BigInteger>): List<BigInteger> {
val tempList = mutableListOf<BigInteger>()
inp.indices.forEach { i ->
tempList += (big255 and rShift(inp[i], 24))
tempList += (big255 and rShift(inp[i], 16))
tempList += (big255 and rShift(inp[i], 8))
tempList += (big255 and inp[i])
}
return tempList
}
private fun unPad(a46: List<BigInteger>): List<BigInteger> {
val evenOdd = a46[0].toInt().mod(2)
return (1 until (a46.size - evenOdd)).map {
a46[it]
}
}
private fun xorBlocks(a76: List<BigInteger>, a77: List<BigInteger>): List<BigInteger> {
return listOf(a76[0] xor a77[0], a76[1] xor a77[1])
}
private fun rShift(input: BigInteger, by: Int): BigInteger {
return (input.mod(4294967296.toBigInteger()) shr by)
}
private fun tearCode(list1: List<BigInteger>, list2: List<BigInteger>): MutableList<BigInteger> {
var a1 = list1[0]
var a2 = list1[1]
var temp = big0
for (_i in 0 until 32) {
a1 += (a2 shl 4 xor rShift(a2, 5)) + a2 xor temp + list2[(temp and big3).toInt()]
temp -= 1640531527.toBigInteger()
a2 += (a1 shl 4 xor rShift(a1, 5)) + a1 xor temp + list2[(rShift(temp, 11) and big3).toInt()]
}
return mutableListOf(a1, a2)
}
private fun ascii2bytes(input: String): List<BigInteger> {
val abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
val abcMap = abc.mapIndexed { i, c -> c to i.toBigInteger() }.toMap()
var index = -1
val length = input.length
var listIndex = 0
val bytes = mutableListOf<BigInteger>()
while (true) {
for (i in input) {
if (abc.contains(i)) {
index++
break
}
}
bytes.add((abcMap[input.getOrNull(index)?:return bytes]!! * big4))
while (true) {
index++
if (abc.contains(input[index])) {
break
}
}
var temp = abcMap[input[index]]!!
bytes[listIndex] = bytes[listIndex] or rShift(temp, 4)
listIndex++
temp = (big15.and(temp))
if ((temp == big0) && (index == (length - 1))) return bytes
bytes.add((temp * big4 * big4))
while (true) {
index++
if (index >= length) return bytes
if (abc.contains(input[index])) break
}
temp = abcMap[input[index]]!!
bytes[listIndex] = bytes[listIndex] or rShift(temp, 2)
listIndex++
temp = (big3 and temp)
if ((temp == big0) && (index == (length - 1))) {
return bytes
}
bytes.add((temp shl 6))
for (i in input) {
index++
if (abc.contains(input[index])) {
break
}
}
bytes[listIndex] = bytes[listIndex] or abcMap[input[index]]!!
listIndex++
}
}
private fun replace(a: String): String {
val map = mapOf(
'0' to '5',
'1' to '6',
'2' to '7',
'5' to '0',
'6' to '1',
'7' to '2'
)
var b = ""
a.forEach {
b += if (map.containsKey(it)) map[it] else it
}
return b
}
private fun padLastChars(input:String):String{
return if(input.reversed()[3].isDigit()) input
else input.dropLast(4)
}
private data class HashResponse(
val hash: String? = null,
val version:String? = null
)
private data class SetupResponse(
val seed: String,
val src: String?=null,
val link:String?=null
)
}
}

View file

@ -115,8 +115,9 @@ open class WcoStream : ExtractorApi() {
)?.destructured) ?: return emptyList() )?.destructured) ?: return emptyList()
// val (skey) = Regex("""skey\s=\s['"](.*?)['"];""").find(html)?.destructured // val (skey) = Regex("""skey\s=\s['"](.*?)['"];""").find(html)?.destructured
// ?: return emptyList() // ?: return emptyList()
keytwo = getWcoKey() ?: return emptyList() val keys = getWcoKey()
val encryptedID = encrypt(cipher(key, encrypt(Id))).replace("/", "_").replace("=","") keytwo = keys?.wcoKey ?: return emptyList()
val encryptedID = encrypt(cipher(keys.wcocipher!!, encrypt(Id))).replace("/", "_").replace("=","")
val apiLink = "$baseUrl/info/$encryptedID" val apiLink = "$baseUrl/info/$encryptedID"
val referrer = "$baseUrl/e/$Id?domain=wcostream.cc" val referrer = "$baseUrl/e/$Id?domain=wcostream.cc"

View file

@ -12,11 +12,10 @@ class WcoHelper {
data class ExternalKeys( data class ExternalKeys(
@JsonProperty("wco_key") @JsonProperty("wco_key")
val wcoKey: String? = null, val wcoKey: String? = null,
@JsonProperty("wco_cipher_key")
val wcocipher: String? = null
) )
private var keys: ExternalKeys? = null private var keys: ExternalKeys? = null
private val wcoKey: String? get() = keys?.wcoKey
private suspend fun getKeys() { private suspend fun getKeys() {
keys = keys keys = keys
?: app.get("https://raw.githubusercontent.com/LagradOst/CloudStream-3/master/docs/keys.json") ?: app.get("https://raw.githubusercontent.com/LagradOst/CloudStream-3/master/docs/keys.json")
@ -25,9 +24,9 @@ class WcoHelper {
) )
} }
suspend fun getWcoKey(): String? { suspend fun getWcoKey(): ExternalKeys? {
getKeys() getKeys()
return wcoKey return keys
} }
} }
} }

View file

@ -354,7 +354,8 @@ open class BflixProvider : MainAPI() {
jsonservers.vidstream, jsonservers.vidstream,
jsonservers.mcloud, jsonservers.mcloud,
jsonservers.mp4upload, jsonservers.mp4upload,
jsonservers.streamtape jsonservers.streamtape,
jsonservers.videovard,
).mapNotNull { ).mapNotNull {
val epserver = app.get("$mainUrl/ajax/episode/info?id=$it").text val epserver = app.get("$mainUrl/ajax/episode/info?id=$it").text
(if (epserver.contains("url")) { (if (epserver.contains("url")) {

View file

@ -119,6 +119,8 @@ val extractorApis: Array<ExtractorApi> = arrayOf(
MwvnVizcloudInfo(), MwvnVizcloudInfo(),
VizcloudDigital(), VizcloudDigital(),
VizcloudCloud(), VizcloudCloud(),
VideoVard(),
VideovardSX(),
Mp4Upload(), Mp4Upload(),
StreamTape(), StreamTape(),

View file

@ -1,3 +1,4 @@
{ {
"wco_key": "51wJ0FDq/UVCefLopEcmK3ni4WIQztMjZdSYOsbHr9R2h7PvxBGAuglaN8+kXT6y" "wco_key": "51wJ0FDq/UVCefLopEcmK3ni4WIQztMjZdSYOsbHr9R2h7PvxBGAuglaN8+kXT6y",
"wco_cipher_key": "vZUFFBPxMqDeOfAm"
} }