sora: update Smasy and add Vizcloud

This commit is contained in:
hexated 2023-04-17 17:01:08 +07:00
parent 753e8a971e
commit ac2b8b9824
5 changed files with 153 additions and 79 deletions

View file

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

View file

@ -811,71 +811,62 @@ object SoraExtractor : SoraStream() {
}
suspend fun invokeFlixhq(
suspend fun invokeFmovies(
title: String? = null,
year: Int? = null,
season: Int? = null,
episode: Int? = null,
lastSeason: Int? = null,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
) {
val fixTitle = title?.replace("", "-")
val id = app.get("$haikeiFlixhqAPI/$title")
.parsedSafe<ConsumetSearchResponse>()?.results?.find {
if (season == null) {
it.title?.equals(
"$fixTitle", true
) == true && it.releaseDate?.equals("$year") == true && it.type == "Movie"
} else {
it.title?.equals(
"$fixTitle",
true
) == true && it.type == "TV Series" && it.seasons == lastSeason
}
}?.id ?: return
val html =
app.get("https://fmovies.to/ajax/film/search?vrf=${encodeVrf("$title")}&keyword=$title")
.parsedSafe<FmoviesSearch>()?.html
val episodeId =
app.get("$haikeiFlixhqAPI/info?id=$id").parsedSafe<ConsumetDetails>()?.let {
if (season == null) {
it.episodes?.first()?.id
} else {
it.episodes?.find { ep -> ep.number == episode && ep.season == season }?.id
}
} ?: return
val mediaId = Jsoup.parse(html ?: return).select("a.item").map {
Triple(
it.attr("href"),
it.select("div.title").text(),
it.selectFirst("i.dot")?.nextSibling().toString().trim(),
)
}.find {
if (season == null) {
it.first.contains("/movie/")
} else {
it.first.contains("/series/")
} && (it.second.equals(title, true) || it.second.createSlug()
.equals(title.createSlug())) && it.third.toInt() == year
}?.first ?: return
listOf(
"vidcloud", "upcloud"
).apmap { server ->
val sources = app.get(
if (server == "upcloud") {
"$haikeiFlixhqAPI/watch?episodeId=$episodeId&mediaId=$id"
} else {
"$haikeiFlixhqAPI/watch?episodeId=$episodeId&mediaId=$id&server=$server"
},
).parsedSafe<ConsumetSourcesResponse>()
val name = fixTitle(server)
sources?.sources?.map {
callback.invoke(
ExtractorLink(
name,
name,
it.url ?: return@map null,
sources.headers?.referer ?: "",
it.quality?.toIntOrNull() ?: Qualities.Unknown.value,
it.isM3U8 ?: true
)
val episodeId = if (season == null) {
"1-full"
} else {
"$season-$episode"
}
val sources = app.get(
"$consumetFmoviesAPI/watch?mediaId=${mediaId.removePrefix("/")}&episodeId=$episodeId"
).parsedSafe<ConsumetSourcesResponse>()
sources?.sources?.map {
callback.invoke(
ExtractorLink(
"Vizcloud",
"Vizcloud",
it.url ?: return@map null,
sources.headers?.referer ?: "",
getQualityFromName(it.quality),
it.isM3U8 ?: true
)
}
)
}
sources?.subtitles?.map {
subtitleCallback.invoke(
SubtitleFile(
it.lang ?: "", it.url ?: return@map null
)
sources?.subtitles?.map {
subtitleCallback.invoke(
SubtitleFile(
it.lang ?: "", it.url ?: return@map null
)
}
)
}
@ -2019,6 +2010,9 @@ object SoraExtractor : SoraStream() {
it.first.contains("/gtop") -> {
invokeSmashyTwo(it.second, it.first, callback)
}
it.first.contains("/dude_tv") -> {
invokeSmashyThree(it.second, it.first, callback)
}
else -> return@apmap
}
}
@ -3492,4 +3486,13 @@ data class CryMoviesStream(
data class CryMoviesResponse(
@JsonProperty("streams") val streams: List<CryMoviesStream>? = null,
)
data class DudetvSources(
@JsonProperty("file") val file: String? = null,
@JsonProperty("title") val title: String? = null,
)
data class FmoviesSearch(
@JsonProperty("html") val html: String? = null,
)

View file

@ -28,6 +28,7 @@ import com.hexated.SoraExtractor.invokeDahmerMovies
import com.hexated.SoraExtractor.invokeEdithxmovies
import com.hexated.SoraExtractor.invokeFDMovies
import com.hexated.SoraExtractor.invokeFlixon
import com.hexated.SoraExtractor.invokeFmovies
import com.hexated.SoraExtractor.invokeFwatayako
import com.hexated.SoraExtractor.invokeGMovies
import com.hexated.SoraExtractor.invokeGdbotMovies
@ -100,11 +101,11 @@ open class SoraStream : TmdbProvider() {
const val filmxyAPI = "https://www.filmxy.vip"
const val kimcartoonAPI = "https://kimcartoon.li"
const val xMovieAPI = "https://xemovies.to"
const val haikeiFlixhqAPI = "https://api.haikei.xyz/movies/flixhq" // disabled due to rate limit
const val consumetFmoviesAPI = "https://api.consumet.org/movies/fmovies"
const val consumetZoroAPI = "https://api.consumet.org/anime/zoro"
const val consumetCrunchyrollAPI = "https://cronchy.consumet.stream" // dead
const val allanimeAPI = "https://api.allanime.to"
const val kissKhAPI = "https://kisskh.me"
const val kissKhAPI = "https://kisskh.co"
const val lingAPI = "https://ling-online.net"
const val uhdmoviesAPI = "https://uhdmovies.vip"
const val fwatayakoAPI = "https://5100.svetacdn.in"
@ -481,17 +482,9 @@ open class SoraStream : TmdbProvider() {
callback
)
},
// {
// invokeFlixhq(
// res.title,
// res.year,
// res.season,
// res.episode,
// res.lastSeason,
// subtitleCallback,
// callback
// )
// },
{
invokeFmovies(res.title, res.airedYear ?: res.year, res.season, res.episode, subtitleCallback, callback)
},
{
invokeKisskh(res.title, res.season, res.episode, subtitleCallback, callback)
},

View file

@ -7,6 +7,7 @@ import com.hexated.SoraExtractor.invokeCrunchyroll
import com.hexated.SoraExtractor.invokeDbgo
import com.hexated.SoraExtractor.invokeFilmxy
import com.hexated.SoraExtractor.invokeFlixon
import com.hexated.SoraExtractor.invokeFmovies
import com.hexated.SoraExtractor.invokeFwatayako
import com.hexated.SoraExtractor.invokeGomovies
import com.hexated.SoraExtractor.invokeHDMovieBox
@ -187,17 +188,16 @@ class SoraStreamLite : SoraStream() {
callback
)
},
// {
// invokeFlixhq(
// res.title,
// res.year,
// res.season,
// res.episode,
// res.lastSeason,
// subtitleCallback,
// callback
// )
// },
{
invokeFmovies(
res.title,
res.airedYear ?: res.year,
res.season,
res.episode,
subtitleCallback,
callback
)
},
{
invokeKisskh(res.title, res.season, res.episode, subtitleCallback, callback)
},

View file

@ -460,6 +460,26 @@ suspend fun invokeSmashyTwo(
)
}
suspend fun invokeSmashyThree(
name: String,
url: String,
callback: (ExtractorLink) -> Unit
) {
val script =
app.get(url).document.selectFirst("script:containsData(player =)")?.data() ?: return
val source = Regex("file:\\s*(\\[.*]),").find(script)?.groupValues?.get(1) ?: return
tryParseJson<ArrayList<DudetvSources>>(source)?.filter { it.title == "English" }?.map {
M3u8Helper.generateM3u8(
"Smashy [Player 2]",
it.file ?: return@map ,
""
).forEach(callback)
}
}
suspend fun getSoraIdAndType(title: String?, year: Int?, season: Int?) : Pair<String, String>? {
val doc = app.get("${base64DecodeAPI("b20=LmM=b2s=a2w=bG8=Ly8=czo=dHA=aHQ=")}/search?keyword=$title").document
val scriptData = doc.select("div.search-list div.search-video-card").map {
@ -1113,6 +1133,64 @@ fun getDeviceId(length: Int = 16): String {
.joinToString("")
}
fun encodeVrf(query: String): String {
return encode(
encryptVrf(
cipherVrf("DZmuZuXqa9O0z3b7", encode(query)),
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
)
)
}
fun encryptVrf(input: String, key: String): String {
if (input.any { it.code > 255 }) throw Exception("illegal characters!")
var output = ""
for (i in input.indices step 3) {
val a = intArrayOf(-1, -1, -1, -1)
a[0] = input[i].code shr 2
a[1] = (3 and input[i].code) shl 4
if (input.length > i + 1) {
a[1] = a[1] or (input[i + 1].code shr 4)
a[2] = (15 and input[i + 1].code) shl 2
}
if (input.length > i + 2) {
a[2] = a[2] or (input[i + 2].code shr 6)
a[3] = 63 and input[i + 2].code
}
for (n in a) {
if (n == -1) output += "="
else {
if (n in 0..63) output += key[n]
}
}
}
return output
}
fun cipherVrf(key: String, text: String): String {
val arr = IntArray(256) { it }
var u = 0
var r: Int
arr.indices.forEach {
u = (u + arr[it] + key[it % key.length].code) % 256
r = arr[it]
arr[it] = arr[u]
arr[u] = r
}
u = 0
var c = 0
return text.indices.map { j ->
c = (c + 1) % 256
u = (u + arr[c]) % 256
r = arr[c]
arr[c] = arr[u]
arr[u] = r
(text[j].code xor arr[(arr[c] + arr[u]) % 256]).toChar()
}.joinToString("")
}
fun String.encodeUrl(): String {
val url = URL(this)
val uri = URI(url.protocol, url.userInfo, url.host, url.port, url.path, url.query, url.ref)
@ -1129,7 +1207,7 @@ fun String.decodeBase64(): String {
return Base64.decode(this, Base64.DEFAULT).toString(Charsets.UTF_8)
}
fun encode(input: String): String? = URLEncoder.encode(input, "utf-8")
fun encode(input: String): String = URLEncoder.encode(input, "utf-8").replace("+", "%20")
fun decryptStreamUrl(data: String): String {