mirror of
https://github.com/hexated/cloudstream-extensions-hexated.git
synced 2024-08-15 00:03:22 +00:00
[Sora] added Baymovies
This commit is contained in:
parent
1e8dfcc789
commit
93cf4840a1
4 changed files with 347 additions and 9 deletions
133
SoraStream/src/main/kotlin/com/hexated/CryptoAES.kt
Normal file
133
SoraStream/src/main/kotlin/com/hexated/CryptoAES.kt
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
package com.hexated
|
||||||
|
|
||||||
|
import android.util.Base64
|
||||||
|
import java.security.MessageDigest
|
||||||
|
import java.security.SecureRandom
|
||||||
|
import java.util.*
|
||||||
|
import javax.crypto.Cipher
|
||||||
|
import javax.crypto.spec.IvParameterSpec
|
||||||
|
import javax.crypto.spec.SecretKeySpec
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
|
// code found on https://stackoverflow.com/a/63701411
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Conforming with CryptoJS AES method
|
||||||
|
*/
|
||||||
|
// see https://gist.github.com/thackerronak/554c985c3001b16810af5fc0eb5c358f
|
||||||
|
@Suppress("unused", "FunctionName", "SameParameterValue")
|
||||||
|
object CryptoAES {
|
||||||
|
|
||||||
|
private const val KEY_SIZE = 256
|
||||||
|
private const val IV_SIZE = 128
|
||||||
|
private const val HASH_CIPHER = "AES/CBC/PKCS5Padding"
|
||||||
|
private const val AES = "AES"
|
||||||
|
private const val KDF_DIGEST = "MD5"
|
||||||
|
|
||||||
|
// Seriously crypto-js, what's wrong with you?
|
||||||
|
private const val APPEND = "Salted__"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt
|
||||||
|
* @param password passphrase
|
||||||
|
* @param plainText plain string
|
||||||
|
*/
|
||||||
|
fun encrypt(password: String, plainText: String): String {
|
||||||
|
val saltBytes = generateSalt(8)
|
||||||
|
val key = ByteArray(KEY_SIZE / 8)
|
||||||
|
val iv = ByteArray(IV_SIZE / 8)
|
||||||
|
EvpKDF(password.toByteArray(), KEY_SIZE, IV_SIZE, saltBytes, key, iv)
|
||||||
|
val keyS = SecretKeySpec(key, AES)
|
||||||
|
val cipher = Cipher.getInstance(HASH_CIPHER)
|
||||||
|
val ivSpec = IvParameterSpec(iv)
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, keyS, ivSpec)
|
||||||
|
val cipherText = cipher.doFinal(plainText.toByteArray())
|
||||||
|
// Thanks kientux for this: https://gist.github.com/kientux/bb48259c6f2133e628ad
|
||||||
|
// Create CryptoJS-like encrypted!
|
||||||
|
val sBytes = APPEND.toByteArray()
|
||||||
|
val b = ByteArray(sBytes.size + saltBytes.size + cipherText.size)
|
||||||
|
System.arraycopy(sBytes, 0, b, 0, sBytes.size)
|
||||||
|
System.arraycopy(saltBytes, 0, b, sBytes.size, saltBytes.size)
|
||||||
|
System.arraycopy(cipherText, 0, b, sBytes.size + saltBytes.size, cipherText.size)
|
||||||
|
val bEncode = Base64.encode(b, Base64.NO_WRAP)
|
||||||
|
return String(bEncode)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypt
|
||||||
|
* Thanks Artjom B. for this: http://stackoverflow.com/a/29152379/4405051
|
||||||
|
* @param password passphrase
|
||||||
|
* @param cipherText encrypted string
|
||||||
|
*/
|
||||||
|
fun decrypt(password: String, cipherText: String): String {
|
||||||
|
val ctBytes = Base64.decode(cipherText.toByteArray(), Base64.NO_WRAP)
|
||||||
|
val saltBytes = Arrays.copyOfRange(ctBytes, 8, 16)
|
||||||
|
val cipherTextBytes = Arrays.copyOfRange(ctBytes, 16, ctBytes.size)
|
||||||
|
val key = ByteArray(KEY_SIZE / 8)
|
||||||
|
val iv = ByteArray(IV_SIZE / 8)
|
||||||
|
EvpKDF(password.toByteArray(), KEY_SIZE, IV_SIZE, saltBytes, key, iv)
|
||||||
|
val cipher = Cipher.getInstance(HASH_CIPHER)
|
||||||
|
val keyS = SecretKeySpec(key, AES)
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, keyS, IvParameterSpec(iv))
|
||||||
|
val plainText = cipher.doFinal(cipherTextBytes)
|
||||||
|
return String(plainText)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun EvpKDF(
|
||||||
|
password: ByteArray,
|
||||||
|
keySize: Int,
|
||||||
|
ivSize: Int,
|
||||||
|
salt: ByteArray,
|
||||||
|
resultKey: ByteArray,
|
||||||
|
resultIv: ByteArray
|
||||||
|
): ByteArray {
|
||||||
|
return EvpKDF(password, keySize, ivSize, salt, 1, KDF_DIGEST, resultKey, resultIv)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("NAME_SHADOWING")
|
||||||
|
private fun EvpKDF(
|
||||||
|
password: ByteArray,
|
||||||
|
keySize: Int,
|
||||||
|
ivSize: Int,
|
||||||
|
salt: ByteArray,
|
||||||
|
iterations: Int,
|
||||||
|
hashAlgorithm: String,
|
||||||
|
resultKey: ByteArray,
|
||||||
|
resultIv: ByteArray
|
||||||
|
): ByteArray {
|
||||||
|
val keySize = keySize / 32
|
||||||
|
val ivSize = ivSize / 32
|
||||||
|
val targetKeySize = keySize + ivSize
|
||||||
|
val derivedBytes = ByteArray(targetKeySize * 4)
|
||||||
|
var numberOfDerivedWords = 0
|
||||||
|
var block: ByteArray? = null
|
||||||
|
val hash = MessageDigest.getInstance(hashAlgorithm)
|
||||||
|
while (numberOfDerivedWords < targetKeySize) {
|
||||||
|
if (block != null) {
|
||||||
|
hash.update(block)
|
||||||
|
}
|
||||||
|
hash.update(password)
|
||||||
|
block = hash.digest(salt)
|
||||||
|
hash.reset()
|
||||||
|
// Iterations
|
||||||
|
for (i in 1 until iterations) {
|
||||||
|
block = hash.digest(block!!)
|
||||||
|
hash.reset()
|
||||||
|
}
|
||||||
|
System.arraycopy(
|
||||||
|
block!!, 0, derivedBytes, numberOfDerivedWords * 4,
|
||||||
|
min(block.size, (targetKeySize - numberOfDerivedWords) * 4)
|
||||||
|
)
|
||||||
|
numberOfDerivedWords += block.size / 4
|
||||||
|
}
|
||||||
|
System.arraycopy(derivedBytes, 0, resultKey, 0, keySize * 4)
|
||||||
|
System.arraycopy(derivedBytes, keySize * 4, resultIv, 0, ivSize * 4)
|
||||||
|
return derivedBytes // key + iv
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateSalt(length: Int): ByteArray {
|
||||||
|
return ByteArray(length).apply {
|
||||||
|
SecureRandom().nextBytes(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package com.hexated
|
package com.hexated
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.utils.*
|
import com.lagradost.cloudstream3.utils.*
|
||||||
|
@ -14,6 +15,7 @@ import com.lagradost.nicehttp.RequestBodyTypes
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
|
import okio.ByteString.Companion.encode
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
|
|
||||||
val session = Session(Requests().baseClient)
|
val session = Session(Requests().baseClient)
|
||||||
|
@ -2022,6 +2024,135 @@ object SoraExtractor : SoraStream() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO only subs
|
||||||
|
suspend fun invokeWatchsomuch(
|
||||||
|
imdbId: String? = null,
|
||||||
|
season: Int? = null,
|
||||||
|
episode: Int? = null,
|
||||||
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
|
) {
|
||||||
|
val watchSomuchAPI = "https://watchsomuch.tv"
|
||||||
|
val id = imdbId?.removePrefix("tt")
|
||||||
|
val epsId = app.post(
|
||||||
|
"$watchSomuchAPI/Watch/ajMovieTorrents.aspx",
|
||||||
|
data = mapOf(
|
||||||
|
"index" to "0",
|
||||||
|
"mid" to "$id",
|
||||||
|
"wsk" to "f6ea6cde-e42b-4c26-98d3-b4fe48cdd4fb",
|
||||||
|
"lid" to "",
|
||||||
|
"liu" to ""
|
||||||
|
), headers = mapOf("X-Requested-With" to "XMLHttpRequest")
|
||||||
|
).parsedSafe<WatchsomuchResponses>()?.movie?.torrents?.let { eps ->
|
||||||
|
if (season == null) {
|
||||||
|
eps.firstOrNull()?.id
|
||||||
|
} else {
|
||||||
|
eps.find { it.episode == episode && it.season == season }?.id
|
||||||
|
}
|
||||||
|
} ?: return
|
||||||
|
|
||||||
|
val subUrl = if (season == null) {
|
||||||
|
"$watchSomuchAPI/Watch/ajMovieSubtitles.aspx?mid=$id&tid=$epsId&part="
|
||||||
|
} else {
|
||||||
|
"$watchSomuchAPI/Watch/ajMovieSubtitles.aspx?mid=$id&tid=$epsId&part=S0${season}E0${episode}"
|
||||||
|
}
|
||||||
|
|
||||||
|
app.get(subUrl)
|
||||||
|
.parsedSafe<WatchsomuchSubResponses>()?.subtitles
|
||||||
|
?.filter { it.url?.startsWith("https") == true }
|
||||||
|
?.map { sub ->
|
||||||
|
Log.i("hexated", "${sub.label} => ${sub.url}")
|
||||||
|
subtitleCallback.invoke(
|
||||||
|
SubtitleFile(
|
||||||
|
sub.label ?: "",
|
||||||
|
sub.url ?: return@map null
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun invokeBaymovies(
|
||||||
|
title: String? = null,
|
||||||
|
year: Int? = null,
|
||||||
|
season: Int? = null,
|
||||||
|
episode: Int? = null,
|
||||||
|
callback: (ExtractorLink) -> Unit,
|
||||||
|
) {
|
||||||
|
val key = base64DecodeAPI("ZW0=c3Q=c3k=b28=YWQ=Ymg=")
|
||||||
|
val headers = mapOf(
|
||||||
|
"Referer" to "$baymovies/",
|
||||||
|
"Origin" to baymovies,
|
||||||
|
"cf_cache_token" to "UKsVpQqBMxB56gBfhYKbfCVkRIXMh42pk6G4DdkXXoVh7j4BjV"
|
||||||
|
)
|
||||||
|
|
||||||
|
val titleSlug = title.fixTitle()?.replace("-", ".") ?: return
|
||||||
|
val (episodeSlug, seasonSlug) = if (season == null) {
|
||||||
|
listOf("", "")
|
||||||
|
} else {
|
||||||
|
listOf(
|
||||||
|
if (episode!! < 10) "0$episode" else episode,
|
||||||
|
if (season < 10) "0$season" else season
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val query = if (season == null) {
|
||||||
|
"$title $year"
|
||||||
|
} else {
|
||||||
|
"$title S${episodeSlug}E${seasonSlug}"
|
||||||
|
}
|
||||||
|
|
||||||
|
val media =
|
||||||
|
app.get("$baymoviesAPI//0:search?q=$query&page_token=&page_index=0", headers = headers)
|
||||||
|
.parsedSafe<BaymoviesSearch>()?.data?.files?.filter { media ->
|
||||||
|
(if (season == null) {
|
||||||
|
media.name?.contains("$year") == true
|
||||||
|
} else {
|
||||||
|
media.name?.contains(Regex("(?i)S${episodeSlug}E${seasonSlug}")) == true
|
||||||
|
}) && media.name?.contains(
|
||||||
|
"720p",
|
||||||
|
true
|
||||||
|
) == false && (media.mimeType == "video/x-matroska" || media.mimeType == "video/mp4") && (media.name.contains(
|
||||||
|
titleSlug,
|
||||||
|
true
|
||||||
|
) || media.name.contains(title ?: return, true))
|
||||||
|
}?.distinctBy { it.name } ?: return
|
||||||
|
|
||||||
|
media.apmap { file ->
|
||||||
|
val expiry = (System.currentTimeMillis() + 345600000).toString()
|
||||||
|
val hmacSign = "${file.id}@$expiry".encode()
|
||||||
|
.hmacSha256(key.encode()).base64().replace("+", "-")
|
||||||
|
val encryptedId =
|
||||||
|
base64Encode(CryptoAES.encrypt(key, file.id ?: return@apmap null).toByteArray())
|
||||||
|
val encryptedExpiry = base64Encode(CryptoAES.encrypt(key, expiry).toByteArray())
|
||||||
|
val worker = getConfig().workers.randomOrNull() ?: return@apmap null
|
||||||
|
|
||||||
|
val link = "https://api.$worker.workers.dev/download.aspx?file=$encryptedId&expiry=$encryptedExpiry&mac=$hmacSign"
|
||||||
|
val size = file.size?.toDouble() ?: return@apmap null
|
||||||
|
val sizeFile = "%.2f GB".format(bytesToGigaBytes(size))
|
||||||
|
val tags = Regex("\\d{3,4}[pP]\\.?(.*?)\\.(mkv|mp4)").find(
|
||||||
|
file.name ?: return@apmap null
|
||||||
|
)?.groupValues?.getOrNull(1)?.replace(".", " ")?.trim()
|
||||||
|
?: ""
|
||||||
|
val quality =
|
||||||
|
Regex("(\\d{3,4})[pP]").find(file.name)?.groupValues?.getOrNull(1)?.toIntOrNull()
|
||||||
|
?: Qualities.Unknown.value
|
||||||
|
|
||||||
|
callback.invoke(
|
||||||
|
ExtractorLink(
|
||||||
|
"Baymovies $tags [$sizeFile]",
|
||||||
|
"Baymovies $tags [$sizeFile]",
|
||||||
|
link,
|
||||||
|
"",
|
||||||
|
quality,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class StreamM4u : XStreamCdn() {
|
class StreamM4u : XStreamCdn() {
|
||||||
|
@ -2041,6 +2172,12 @@ data class FDMovieIFrame(
|
||||||
val type: String,
|
val type: String,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class BaymoviesConfig(
|
||||||
|
val country: String,
|
||||||
|
val downloadTime: String,
|
||||||
|
val workers: List<String>
|
||||||
|
)
|
||||||
|
|
||||||
data class Movie123Media(
|
data class Movie123Media(
|
||||||
@JsonProperty("url") val url: String? = null,
|
@JsonProperty("url") val url: String? = null,
|
||||||
)
|
)
|
||||||
|
@ -2301,3 +2438,44 @@ data class Smashy1Source(
|
||||||
@JsonProperty("file") val file: String? = null,
|
@JsonProperty("file") val file: String? = null,
|
||||||
@JsonProperty("tracks") val tracks: ArrayList<Smashy1Tracks>? = arrayListOf(),
|
@JsonProperty("tracks") val tracks: ArrayList<Smashy1Tracks>? = arrayListOf(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class WatchsomuchTorrents(
|
||||||
|
@JsonProperty("id") val id: Int? = null,
|
||||||
|
@JsonProperty("movieId") val movieId: Int? = null,
|
||||||
|
@JsonProperty("season") val season: Int? = null,
|
||||||
|
@JsonProperty("episode") val episode: Int? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class WatchsomuchMovies(
|
||||||
|
@JsonProperty("torrents") val torrents: ArrayList<WatchsomuchTorrents>? = arrayListOf(),
|
||||||
|
)
|
||||||
|
|
||||||
|
data class WatchsomuchResponses(
|
||||||
|
@JsonProperty("movie") val movie: WatchsomuchMovies? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class WatchsomuchSubtitles(
|
||||||
|
@JsonProperty("url") val url: String? = null,
|
||||||
|
@JsonProperty("label") val label: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class WatchsomuchSubResponses(
|
||||||
|
@JsonProperty("subtitles") val subtitles: ArrayList<WatchsomuchSubtitles>? = arrayListOf(),
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Baymovies(
|
||||||
|
@JsonProperty("id") val id: String? = null,
|
||||||
|
@JsonProperty("driveId") val driveId: String? = null,
|
||||||
|
@JsonProperty("mimeType") val mimeType: String? = null,
|
||||||
|
@JsonProperty("size") val size: String? = null,
|
||||||
|
@JsonProperty("name") val name: String? = null,
|
||||||
|
@JsonProperty("modifiedTime") val modifiedTime: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class BaymoviesData(
|
||||||
|
@JsonProperty("files") val files: ArrayList<Baymovies>? = arrayListOf(),
|
||||||
|
)
|
||||||
|
|
||||||
|
data class BaymoviesSearch(
|
||||||
|
@JsonProperty("data") val data: BaymoviesData? = null,
|
||||||
|
)
|
|
@ -3,6 +3,7 @@ package com.hexated
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
import com.hexated.SoraExtractor.invoke123Movie
|
import com.hexated.SoraExtractor.invoke123Movie
|
||||||
import com.hexated.SoraExtractor.invokeAnimes
|
import com.hexated.SoraExtractor.invokeAnimes
|
||||||
|
import com.hexated.SoraExtractor.invokeBaymovies
|
||||||
import com.hexated.SoraExtractor.invokeBollyMaza
|
import com.hexated.SoraExtractor.invokeBollyMaza
|
||||||
import com.hexated.SoraExtractor.invokeDbgo
|
import com.hexated.SoraExtractor.invokeDbgo
|
||||||
import com.hexated.SoraExtractor.invokeFilmxy
|
import com.hexated.SoraExtractor.invokeFilmxy
|
||||||
|
@ -65,12 +66,11 @@ open class SoraStream : TmdbProvider() {
|
||||||
const val consumetAnilistAPI = "https://api.consumet.org/meta/anilist"
|
const val consumetAnilistAPI = "https://api.consumet.org/meta/anilist"
|
||||||
const val kamyrollAPI = "https://api.kamyroll.tech"
|
const val kamyrollAPI = "https://api.kamyroll.tech"
|
||||||
|
|
||||||
private val mainAPI =
|
private val mainAPI = base64DecodeAPI("cHA=LmE=ZWw=cmM=dmU=aC4=dGM=d2E=eHA=Ly8=czo=dHA=aHQ=")
|
||||||
base64DecodeAPI("cHA=LmE=ZWw=cmM=dmU=aC4=dGM=d2E=eHA=Ly8=czo=dHA=aHQ=")
|
var baymovies = base64DecodeAPI("Zw==b3I=dS4=LmU=ZXg=bmQ=emk=aS4=YXA=dXA=cm8=Y2c=bGk=dWI=eHA=ZGU=aW4=YXk=ZWI=dGg=Ly8=czo=dHA=aHQ=")
|
||||||
|
|
||||||
// private var mainServerAPI = base64DecodeAPI("cA==YXA=bC4=Y2U=ZXI=LnY=aWU=b3Y=LW0=cmE=c28=Ly8=czo=dHA=aHQ=")
|
// private var mainServerAPI = base64DecodeAPI("cA==YXA=bC4=Y2U=ZXI=LnY=aWU=b3Y=LW0=cmE=c28=Ly8=czo=dHA=aHQ=")
|
||||||
var netMoviesAPI =
|
var netMoviesAPI = base64DecodeAPI("aQ==YXA=cC8=YXA=bC4=Y2U=ZXI=LnY=bG0=Zmk=dC0=bmU=Ly8=czo=dHA=aHQ=")
|
||||||
base64DecodeAPI("aQ==YXA=cC8=YXA=bC4=Y2U=ZXI=LnY=bG0=Zmk=dC0=bmU=Ly8=czo=dHA=aHQ=")
|
|
||||||
const val twoEmbedAPI = "https://www.2embed.to"
|
const val twoEmbedAPI = "https://www.2embed.to"
|
||||||
const val vidSrcAPI = "https://v2.vidsrc.me"
|
const val vidSrcAPI = "https://v2.vidsrc.me"
|
||||||
const val dbgoAPI = "https://dbgo.fun"
|
const val dbgoAPI = "https://dbgo.fun"
|
||||||
|
@ -105,6 +105,7 @@ open class SoraStream : TmdbProvider() {
|
||||||
const val animeKaizokuAPI = "https://animekaizoku.com"
|
const val animeKaizokuAPI = "https://animekaizoku.com"
|
||||||
const val movie123NetAPI = "https://ww7.0123movie.net"
|
const val movie123NetAPI = "https://ww7.0123movie.net"
|
||||||
const val smashyStreamAPI = "https://embed.smashystream.com"
|
const val smashyStreamAPI = "https://embed.smashystream.com"
|
||||||
|
const val baymoviesAPI = "https://thebayindexpublicgroupapi.zindex.eu.org"
|
||||||
|
|
||||||
fun getType(t: String?): TvType {
|
fun getType(t: String?): TvType {
|
||||||
return when (t) {
|
return when (t) {
|
||||||
|
@ -529,6 +530,15 @@ open class SoraStream : TmdbProvider() {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
invokeSmashyStream(res.id, res.season, res.episode, subtitleCallback, callback)
|
invokeSmashyStream(res.id, res.season, res.episode, subtitleCallback, callback)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
if(!res.isAnime) invokeBaymovies(
|
||||||
|
res.title,
|
||||||
|
res.year,
|
||||||
|
res.season,
|
||||||
|
res.episode,
|
||||||
|
callback
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
package com.hexated
|
package com.hexated
|
||||||
|
|
||||||
|
import com.hexated.SoraStream.Companion.baymovies
|
||||||
import com.hexated.SoraStream.Companion.consumetCrunchyrollAPI
|
import com.hexated.SoraStream.Companion.consumetCrunchyrollAPI
|
||||||
import com.hexated.SoraStream.Companion.filmxyAPI
|
import com.hexated.SoraStream.Companion.filmxyAPI
|
||||||
import com.hexated.SoraStream.Companion.gdbot
|
import com.hexated.SoraStream.Companion.gdbot
|
||||||
import com.hexated.SoraStream.Companion.kamyrollAPI
|
import com.hexated.SoraStream.Companion.kamyrollAPI
|
||||||
import com.hexated.SoraStream.Companion.tvMoviesAPI
|
import com.hexated.SoraStream.Companion.tvMoviesAPI
|
||||||
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.APIHolder.getCaptchaToken
|
import com.lagradost.cloudstream3.APIHolder.getCaptchaToken
|
||||||
import com.lagradost.cloudstream3.SubtitleFile
|
|
||||||
import com.lagradost.cloudstream3.app
|
|
||||||
import com.lagradost.cloudstream3.base64Decode
|
|
||||||
import com.lagradost.cloudstream3.base64Encode
|
|
||||||
import com.lagradost.cloudstream3.network.WebViewResolver
|
import com.lagradost.cloudstream3.network.WebViewResolver
|
||||||
import com.lagradost.cloudstream3.utils.*
|
import com.lagradost.cloudstream3.utils.*
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
||||||
|
@ -600,6 +598,23 @@ fun List<HashMap<String, String>>?.matchingEpisode(episode: Int?): String? {
|
||||||
}?.get("id")
|
}?.get("id")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun getConfig(): BaymoviesConfig {
|
||||||
|
val regex = """const country = "(.*?)";
|
||||||
|
const downloadtime = "(.*?)";
|
||||||
|
var arrayofworkers = (.*)""".toRegex()
|
||||||
|
val js = app.get(
|
||||||
|
"https://geolocation.zindex.eu.org/api.js",
|
||||||
|
referer = "$baymovies/",
|
||||||
|
).text
|
||||||
|
val match = regex.find(js) ?: throw ErrorLoadingException()
|
||||||
|
val country = match.groupValues[1]
|
||||||
|
val downloadTime = match.groupValues[2]
|
||||||
|
val workers = tryParseJson<List<String>>(match.groupValues[3])
|
||||||
|
?: throw ErrorLoadingException()
|
||||||
|
|
||||||
|
return BaymoviesConfig(country, downloadTime, workers)
|
||||||
|
}
|
||||||
|
|
||||||
fun String?.fixTitle(): String? {
|
fun String?.fixTitle(): String? {
|
||||||
return this?.replace(Regex("[!%:'?,]|( &)"), "")?.replace(" ", "-")?.lowercase()
|
return this?.replace(Regex("[!%:'?,]|( &)"), "")?.replace(" ", "-")?.lowercase()
|
||||||
?.replace("-–-", "-")
|
?.replace("-–-", "-")
|
||||||
|
@ -609,6 +624,8 @@ fun getLanguage(str: String): String {
|
||||||
return if (str.contains("(in_ID)")) "Indonesian" else str
|
return if (str.contains("(in_ID)")) "Indonesian" else str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun bytesToGigaBytes( number: Double ): Double = number / 1024000000
|
||||||
|
|
||||||
fun getKisskhTitle(str: String?): String? {
|
fun getKisskhTitle(str: String?): String? {
|
||||||
return str?.replace(Regex("[^a-zA-Z0-9]"), "-")
|
return str?.replace(Regex("[^a-zA-Z0-9]"), "-")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue