mirror of
https://github.com/hexated/cloudstream-extensions-hexated.git
synced 2024-08-15 00:03:22 +00:00
sora: fix sources
This commit is contained in:
parent
f70d881db0
commit
3702430c02
5 changed files with 97 additions and 44 deletions
|
@ -1,7 +1,7 @@
|
||||||
import org.jetbrains.kotlin.konan.properties.Properties
|
import org.jetbrains.kotlin.konan.properties.Properties
|
||||||
|
|
||||||
// use an integer for version numbers
|
// use an integer for version numbers
|
||||||
version = 134
|
version = 135
|
||||||
|
|
||||||
android {
|
android {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
|
|
|
@ -730,14 +730,14 @@ object SoraExtractor : SoraStream() {
|
||||||
) {
|
) {
|
||||||
val query = title?.replace(Regex("[^\\w-\\s]"), "")
|
val query = title?.replace(Regex("[^\\w-\\s]"), "")
|
||||||
val html =
|
val html =
|
||||||
app.get("$fmoviesAPI/ajax/film/search?vrf=${encodeVrf("$query")}&keyword=$query")
|
app.get("$fmoviesAPI/ajax/film/search?keyword=$query")
|
||||||
.parsedSafe<FmoviesResponses>()?.html
|
.parsedSafe<FmoviesResponses>()?.result?.html
|
||||||
|
|
||||||
val mediaId = Jsoup.parse(html ?: return).select("a.item").map {
|
val mediaId = Jsoup.parse(html ?: return).select("a.item").map {
|
||||||
Triple(
|
Triple(
|
||||||
it.attr("href"),
|
it.attr("href"),
|
||||||
it.select("div.title").text(),
|
it.select("div.name").text(),
|
||||||
it.selectFirst("i.dot")?.nextSibling().toString().trim(),
|
it.select("span.dot")[1].text(),
|
||||||
)
|
)
|
||||||
}.find {
|
}.find {
|
||||||
if (season == null) {
|
if (season == null) {
|
||||||
|
@ -746,38 +746,35 @@ object SoraExtractor : SoraStream() {
|
||||||
it.first.contains("/series/")
|
it.first.contains("/series/")
|
||||||
} && (it.second.equals(title, true) || it.second.createSlug()
|
} && (it.second.equals(title, true) || it.second.createSlug()
|
||||||
.equals(title.createSlug())) && it.third.toInt() == year
|
.equals(title.createSlug())) && it.third.toInt() == year
|
||||||
}?.first?.substringAfterLast("-") ?: return
|
}?.first
|
||||||
|
|
||||||
val episodeId = if (season == null) {
|
val watchId =
|
||||||
"1-full"
|
app.get(fixUrl(mediaId ?: return, fmoviesAPI)).document.selectFirst("div.watch")
|
||||||
|
?.attr("data-id")
|
||||||
|
|
||||||
|
val episodeId = app.get(
|
||||||
|
"$fmoviesAPI/ajax/episode/list/${watchId ?: return}?vrf=${
|
||||||
|
comsumetEncodeVrf(watchId)
|
||||||
|
}"
|
||||||
|
).parsedSafe<FmoviesResult>()?.result?.let { Jsoup.parse(it) }
|
||||||
|
?.selectFirst("ul[data-season=${season ?: 1}] li a[data-num=${episode ?: 1}]")
|
||||||
|
?.attr("data-id")
|
||||||
|
|
||||||
|
val servers =
|
||||||
|
app.get("$fmoviesAPI/ajax/server/list/${episodeId ?: return}?vrf=${comsumetEncodeVrf(episodeId)}")
|
||||||
|
.parsedSafe<FmoviesResult>()?.result?.let { Jsoup.parse(it) }
|
||||||
|
?.select("ul li")?.map { it.attr("data-id") to it.attr("data-link-id") }
|
||||||
|
|
||||||
|
servers?.filter {
|
||||||
|
it.first == "41" || it.first == "45"
|
||||||
|
}?.apmap { (serverid, linkId) ->
|
||||||
|
delay(2000)
|
||||||
|
val decryptServer = app.get("$fmoviesAPI/ajax/server/$linkId?vrf=${comsumetEncodeVrf(linkId)}")
|
||||||
|
.parsedSafe<FmoviesResponses>()?.result?.url?.let { comsumetDecodeVrf(it) }
|
||||||
|
if (serverid == "41") {
|
||||||
|
invokeVizcloud(serverid, decryptServer ?: return@apmap, subtitleCallback, callback)
|
||||||
} else {
|
} else {
|
||||||
"$season-$episode"
|
loadExtractor(decryptServer ?: return@apmap, fmoviesAPI, subtitleCallback, callback)
|
||||||
}
|
|
||||||
|
|
||||||
val serversKname =
|
|
||||||
app.get("$fmoviesAPI/ajax/film/servers?id=$mediaId&vrf=${encodeVrf(mediaId)}")
|
|
||||||
.parsedSafe<FmoviesResponses>()?.html?.let { Jsoup.parse(it) }
|
|
||||||
?.selectFirst("a[data-kname=$episodeId]")?.attr("data-ep")
|
|
||||||
|
|
||||||
val servers = tryParseJson<HashMap<String, String>>(serversKname)
|
|
||||||
|
|
||||||
val sub = app.get("$fmoviesAPI/ajax/episode/subtitles/${servers?.get("28")}").text
|
|
||||||
tryParseJson<List<FmoviesSubtitles>>(sub)?.map {
|
|
||||||
subtitleCallback.invoke(
|
|
||||||
SubtitleFile(
|
|
||||||
it.label ?: "",
|
|
||||||
it.file ?: return@map
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
servers?.apmap { server ->
|
|
||||||
val decryptServer = app.get("$fmoviesAPI/ajax/episode/info?id=${server.value}")
|
|
||||||
.parsedSafe<FmoviesResponses>()?.url?.let { decodeVrf(it) } ?: return@apmap
|
|
||||||
if (server.key == "41") {
|
|
||||||
invokeVizcloud(decryptServer, callback)
|
|
||||||
} else {
|
|
||||||
loadExtractor(decryptServer, fmoviesAPI, subtitleCallback, callback)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3236,7 +3233,12 @@ data class DudetvSources(
|
||||||
)
|
)
|
||||||
|
|
||||||
data class FmoviesResponses(
|
data class FmoviesResponses(
|
||||||
|
@JsonProperty("result") val result: FmoviesResult? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class FmoviesResult(
|
||||||
@JsonProperty("html") val html: String? = null,
|
@JsonProperty("html") val html: String? = null,
|
||||||
|
@JsonProperty("result") val result: String? = null,
|
||||||
@JsonProperty("url") val url: String? = null,
|
@JsonProperty("url") val url: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,7 @@ open class SoraStream : TmdbProvider() {
|
||||||
const val gdbot = "https://gdtot.pro"
|
const val gdbot = "https://gdtot.pro"
|
||||||
const val anilistAPI = "https://graphql.anilist.co"
|
const val anilistAPI = "https://graphql.anilist.co"
|
||||||
const val malsyncAPI = "https://api.malsync.moe"
|
const val malsyncAPI = "https://api.malsync.moe"
|
||||||
|
const val consumetHelper = "https://api.consumet.org/anime/9anime/helper"
|
||||||
|
|
||||||
private val apiKey =
|
private val apiKey =
|
||||||
base64DecodeAPI("ZTM=NTg=MjM=MjM=ODc=MzI=OGQ=MmE=Nzk=Nzk=ZjI=NTA=NDY=NDA=MzA=YjA=") // PLEASE DON'T STEAL
|
base64DecodeAPI("ZTM=NTg=MjM=MjM=ODc=MzI=OGQ=MmE=Nzk=Nzk=ZjI=NTA=NDY=NDA=MzA=YjA=") // PLEASE DON'T STEAL
|
||||||
|
@ -106,8 +107,8 @@ open class SoraStream : TmdbProvider() {
|
||||||
const val fdMoviesAPI = "https://freedrivemovie.lol"
|
const val fdMoviesAPI = "https://freedrivemovie.lol"
|
||||||
const val m4uhdAPI = "https://m4uhd.tv"
|
const val m4uhdAPI = "https://m4uhd.tv"
|
||||||
const val tvMoviesAPI = "https://www.tvseriesnmovies.com"
|
const val tvMoviesAPI = "https://www.tvseriesnmovies.com"
|
||||||
const val moviezAddAPI = "https://ww1.moviezaddiction.click"
|
const val moviezAddAPI = "https://ww2.moviezaddiction.click"
|
||||||
const val bollyMazaAPI = "https://ww1.bollymaza.click"
|
const val bollyMazaAPI = "https://m.bollymaza.click"
|
||||||
const val moviesbayAPI = "https://moviesbay.live"
|
const val moviesbayAPI = "https://moviesbay.live"
|
||||||
const val rStreamAPI = "https://remotestre.am"
|
const val rStreamAPI = "https://remotestre.am"
|
||||||
const val flixonAPI = "https://flixon.ru"
|
const val flixonAPI = "https://flixon.ru"
|
||||||
|
@ -117,7 +118,7 @@ open class SoraStream : TmdbProvider() {
|
||||||
const val watchSomuchAPI = "https://watchsomuch.tv" // sub only
|
const val watchSomuchAPI = "https://watchsomuch.tv" // sub only
|
||||||
val gomoviesAPI =
|
val gomoviesAPI =
|
||||||
base64DecodeAPI("bQ==Y28=ZS4=aW4=bmw=LW8=ZXM=dmk=bW8=Z28=Ly8=czo=dHA=aHQ=")
|
base64DecodeAPI("bQ==Y28=ZS4=aW4=bmw=LW8=ZXM=dmk=bW8=Z28=Ly8=czo=dHA=aHQ=")
|
||||||
const val ask4MoviesAPI = "https://ask4movie.mx"
|
const val ask4MoviesAPI = "https://ask4movie.net"
|
||||||
const val biliBiliAPI = "https://api-vn.kaguya.app/server"
|
const val biliBiliAPI = "https://api-vn.kaguya.app/server"
|
||||||
const val watchOnlineAPI = "https://watchonline.ag"
|
const val watchOnlineAPI = "https://watchonline.ag"
|
||||||
const val nineTvAPI = "https://api.9animetv.live"
|
const val nineTvAPI = "https://api.9animetv.live"
|
||||||
|
@ -140,7 +141,6 @@ open class SoraStream : TmdbProvider() {
|
||||||
base64DecodeAPI("ZXY=LmQ=cnM=a2U=b3I=Lnc=ZXI=ZGQ=bGE=cy0=b2I=YWM=Lmo=YWw=aW4=LWY=cm4=Ym8=cmU=Ly8=czo=dHA=aHQ=")
|
base64DecodeAPI("ZXY=LmQ=cnM=a2U=b3I=Lnc=ZXI=ZGQ=bGE=cy0=b2I=YWM=Lmo=YWw=aW4=LWY=cm4=Ym8=cmU=Ly8=czo=dHA=aHQ=")
|
||||||
|
|
||||||
// DEAD SITE
|
// DEAD SITE
|
||||||
const val consumetCrunchyrollAPI = "https://cronchy.consumet.stream" // dead
|
|
||||||
const val chillmovies0API = "https://chill.aicirou.workers.dev/0:" // dead
|
const val chillmovies0API = "https://chill.aicirou.workers.dev/0:" // dead
|
||||||
const val chillmovies1API = "https://chill.aicirou.workers.dev/1:" // dead
|
const val chillmovies1API = "https://chill.aicirou.workers.dev/1:" // dead
|
||||||
const val gamMoviesAPI = "https://drive.gamick.workers.dev/0:" // dead
|
const val gamMoviesAPI = "https://drive.gamick.workers.dev/0:" // dead
|
||||||
|
@ -503,7 +503,7 @@ open class SoraStream : TmdbProvider() {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
invokeFmovies(
|
if (!res.isAnime) invokeFmovies(
|
||||||
res.title,
|
res.title,
|
||||||
res.airedYear ?: res.year,
|
res.airedYear ?: res.year,
|
||||||
res.season,
|
res.season,
|
||||||
|
@ -610,7 +610,14 @@ open class SoraStream : TmdbProvider() {
|
||||||
invokeMovie123Net(res.title, res.season, res.episode, subtitleCallback, callback)
|
invokeMovie123Net(res.title, res.season, res.episode, subtitleCallback, callback)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
invokeSmashyStream(res.imdbId, res.season, res.episode, res.isAnime, subtitleCallback, callback)
|
invokeSmashyStream(
|
||||||
|
res.imdbId,
|
||||||
|
res.season,
|
||||||
|
res.episode,
|
||||||
|
res.isAnime,
|
||||||
|
subtitleCallback,
|
||||||
|
callback
|
||||||
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
invokeWatchsomuch(
|
invokeWatchsomuch(
|
||||||
|
|
|
@ -145,7 +145,14 @@ class SoraStreamLite : SoraStream() {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
invokeSeries9(res.title, res.year, res.season, res.episode, subtitleCallback, callback)
|
invokeSeries9(
|
||||||
|
res.title,
|
||||||
|
res.year,
|
||||||
|
res.season,
|
||||||
|
res.episode,
|
||||||
|
subtitleCallback,
|
||||||
|
callback
|
||||||
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
invokeIdlix(
|
invokeIdlix(
|
||||||
|
@ -168,13 +175,26 @@ class SoraStreamLite : SoraStream() {
|
||||||
// )
|
// )
|
||||||
// },
|
// },
|
||||||
{
|
{
|
||||||
if (!res.isAnime) invokeFilmxy(res.imdbId, res.season, res.episode, subtitleCallback, callback)
|
if (!res.isAnime) invokeFilmxy(
|
||||||
|
res.imdbId,
|
||||||
|
res.season,
|
||||||
|
res.episode,
|
||||||
|
subtitleCallback,
|
||||||
|
callback
|
||||||
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
invokeKimcartoon(res.title, res.season, res.episode, subtitleCallback, callback)
|
invokeKimcartoon(res.title, res.season, res.episode, subtitleCallback, callback)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
invokeSmashyStream(res.imdbId, res.season, res.episode, res.isAnime, subtitleCallback, callback)
|
invokeSmashyStream(
|
||||||
|
res.imdbId,
|
||||||
|
res.season,
|
||||||
|
res.episode,
|
||||||
|
res.isAnime,
|
||||||
|
subtitleCallback,
|
||||||
|
callback
|
||||||
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
invokeXmovies(
|
invokeXmovies(
|
||||||
|
@ -187,7 +207,7 @@ class SoraStreamLite : SoraStream() {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
invokeFmovies(
|
if (!res.isAnime) invokeFmovies(
|
||||||
res.title,
|
res.title,
|
||||||
res.airedYear ?: res.year,
|
res.airedYear ?: res.year,
|
||||||
res.season,
|
res.season,
|
||||||
|
|
|
@ -5,8 +5,10 @@ import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
import com.hexated.SoraStream.Companion.anilistAPI
|
import com.hexated.SoraStream.Companion.anilistAPI
|
||||||
import com.hexated.SoraStream.Companion.base64DecodeAPI
|
import com.hexated.SoraStream.Companion.base64DecodeAPI
|
||||||
import com.hexated.SoraStream.Companion.baymoviesAPI
|
import com.hexated.SoraStream.Companion.baymoviesAPI
|
||||||
|
import com.hexated.SoraStream.Companion.consumetHelper
|
||||||
import com.hexated.SoraStream.Companion.crunchyrollAPI
|
import com.hexated.SoraStream.Companion.crunchyrollAPI
|
||||||
import com.hexated.SoraStream.Companion.filmxyAPI
|
import com.hexated.SoraStream.Companion.filmxyAPI
|
||||||
|
import com.hexated.SoraStream.Companion.fmoviesAPI
|
||||||
import com.hexated.SoraStream.Companion.gdbot
|
import com.hexated.SoraStream.Companion.gdbot
|
||||||
import com.hexated.SoraStream.Companion.malsyncAPI
|
import com.hexated.SoraStream.Companion.malsyncAPI
|
||||||
import com.hexated.SoraStream.Companion.putlockerAPI
|
import com.hexated.SoraStream.Companion.putlockerAPI
|
||||||
|
@ -400,11 +402,13 @@ suspend fun getDirectGdrive(url: String): String {
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun invokeVizcloud(
|
suspend fun invokeVizcloud(
|
||||||
|
serverid: String,
|
||||||
url: String,
|
url: String,
|
||||||
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
callback: (ExtractorLink) -> Unit,
|
callback: (ExtractorLink) -> Unit,
|
||||||
) {
|
) {
|
||||||
val id = Regex("(?:embed-|/e/)([^?]*)").find(url)?.groupValues?.getOrNull(1)
|
val id = Regex("(?:/embed[-/]|/e/)([^?/]*)").find(url)?.groupValues?.getOrNull(1)
|
||||||
app.get("https://api.consumet.org/anime/9anime/helper?query=${id ?: return}&action=vizcloud")
|
app.get("$consumetHelper?query=${id ?: return}&action=vizcloud")
|
||||||
.parsedSafe<VizcloudResponses>()?.data?.media?.sources?.map {
|
.parsedSafe<VizcloudResponses>()?.data?.media?.sources?.map {
|
||||||
M3u8Helper.generateM3u8(
|
M3u8Helper.generateM3u8(
|
||||||
"Vizcloud",
|
"Vizcloud",
|
||||||
|
@ -412,6 +416,16 @@ suspend fun invokeVizcloud(
|
||||||
"${getBaseUrl(url)}/"
|
"${getBaseUrl(url)}/"
|
||||||
).forEach(callback)
|
).forEach(callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val sub = app.get("${fmoviesAPI}/ajax/episode/subtitles/$serverid")
|
||||||
|
tryParseJson<List<FmoviesSubtitles>>(sub.text)?.map {
|
||||||
|
subtitleCallback.invoke(
|
||||||
|
SubtitleFile(
|
||||||
|
it.label ?: "",
|
||||||
|
it.file ?: return@map
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun invokeSmashyFfix(
|
suspend fun invokeSmashyFfix(
|
||||||
|
@ -1357,6 +1371,16 @@ fun getDeviceId(length: Int = 16): String {
|
||||||
.joinToString("")
|
.joinToString("")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun comsumetEncodeVrf(query: String): String? {
|
||||||
|
return app.get("$consumetHelper?query=$query&action=fmovies-vrf")
|
||||||
|
.parsedSafe<Map<String, String>>()?.get("url")
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun comsumetDecodeVrf(query: String): String? {
|
||||||
|
val res = app.get("$consumetHelper?query=$query&action=fmovies-decrypt")
|
||||||
|
return tryParseJson<Map<String, String>>(res.text)?.get("url")
|
||||||
|
}
|
||||||
|
|
||||||
fun encodeVrf(query: String): String {
|
fun encodeVrf(query: String): String {
|
||||||
return encode(
|
return encode(
|
||||||
encryptVrf(
|
encryptVrf(
|
||||||
|
|
Loading…
Reference in a new issue