mirror of
https://github.com/hexated/cloudstream-extensions-hexated.git
synced 2024-08-15 00:03:22 +00:00
added new anime Sources into SoraExtractor
This commit is contained in:
parent
10cebd58a9
commit
4c9e9555a0
4 changed files with 243 additions and 1975 deletions
|
@ -1,5 +1,5 @@
|
|||
// use an integer for version numbers
|
||||
version = 30
|
||||
version = 31
|
||||
|
||||
|
||||
cloudstream {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -19,6 +19,7 @@ val session = Session(Requests().baseClient)
|
|||
|
||||
object SoraExtractor : SoraStream() {
|
||||
|
||||
/*
|
||||
suspend fun invokeLocalSources(
|
||||
url: String,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
@ -56,6 +57,7 @@ object SoraExtractor : SoraStream() {
|
|||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
suspend fun invokeTwoEmbed(
|
||||
id: Int? = null,
|
||||
|
@ -303,79 +305,55 @@ object SoraExtractor : SoraStream() {
|
|||
loadExtractor(url, databaseGdriveAPI, subtitleCallback, callback)
|
||||
}
|
||||
|
||||
/* suspend fun invokeSoraVIP(
|
||||
title: String? = null,
|
||||
orgTitle: String? = null,
|
||||
year: Int? = null,
|
||||
season: Int? = null,
|
||||
episode: Int? = null,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
) {
|
||||
val apiUrl = base64DecodeAPI("aQ==YXA=cC8=YXA=bC4=Y2U=ZXI=LnY=b2s=a2w=bG8=Ly8=czo=dHA=aHQ=")
|
||||
val url = if(season == null) {
|
||||
"$apiUrl/search/one?title=$title&orgTitle=$orgTitle&year=$year"
|
||||
} else {
|
||||
"$apiUrl/search/one?title=$title&orgTitle=$orgTitle&year=$year&season=$season"
|
||||
}
|
||||
/* suspend fun invokeSoraVIP(
|
||||
title: String? = null,
|
||||
orgTitle: String? = null,
|
||||
year: Int? = null,
|
||||
season: Int? = null,
|
||||
episode: Int? = null,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
) {
|
||||
val apiUrl = base64DecodeAPI("aQ==YXA=cC8=YXA=bC4=Y2U=ZXI=LnY=b2s=a2w=bG8=Ly8=czo=dHA=aHQ=")
|
||||
val url = if(season == null) {
|
||||
"$apiUrl/search/one?title=$title&orgTitle=$orgTitle&year=$year"
|
||||
} else {
|
||||
"$apiUrl/search/one?title=$title&orgTitle=$orgTitle&year=$year&season=$season"
|
||||
}
|
||||
|
||||
val id = app.get(url).parsedSafe<DetailVipResult>()?.data?.id
|
||||
val id = app.get(url).parsedSafe<DetailVipResult>()?.data?.id
|
||||
|
||||
val sourcesUrl = if(season == null) {
|
||||
"$apiUrl/movie/detail?id=$id"
|
||||
} else {
|
||||
"$apiUrl/tv/detail?id=$id&episodeId=${episode?.minus(1)}"
|
||||
}
|
||||
val sourcesUrl = if(season == null) {
|
||||
"$apiUrl/movie/detail?id=$id"
|
||||
} else {
|
||||
"$apiUrl/tv/detail?id=$id&episodeId=${episode?.minus(1)}"
|
||||
}
|
||||
|
||||
val json = app.get(sourcesUrl).parsedSafe<LoadVIPLinks>()
|
||||
val json = app.get(sourcesUrl).parsedSafe<LoadVIPLinks>()
|
||||
|
||||
json?.sources?.map { source ->
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
"${this.name} (VIP)",
|
||||
"${this.name} (VIP)",
|
||||
source.url ?: return@map null,
|
||||
"$apiUrl/",
|
||||
source.quality ?: Qualities.Unknown.value,
|
||||
isM3u8 = source.url.contains(".m3u8"),
|
||||
json?.sources?.map { source ->
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
"${this.name} (VIP)",
|
||||
"${this.name} (VIP)",
|
||||
source.url ?: return@map null,
|
||||
"$apiUrl/",
|
||||
source.quality ?: Qualities.Unknown.value,
|
||||
isM3u8 = source.url.contains(".m3u8"),
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
json?.subtitles?.map { sub ->
|
||||
subtitleCallback.invoke(
|
||||
SubtitleFile(
|
||||
getLanguage(sub.language.toString()),
|
||||
sub.url ?: return@map null
|
||||
json?.subtitles?.map { sub ->
|
||||
subtitleCallback.invoke(
|
||||
SubtitleFile(
|
||||
getLanguage(sub.language.toString()),
|
||||
sub.url ?: return@map null
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
suspend fun invokeGogo(
|
||||
aniId: String? = null,
|
||||
animeId: String? = null,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
) {
|
||||
val res =
|
||||
app.get("$mainServerAPI/anime/$aniId/episode/$animeId?_data=routes/anime/\$animeId.episode.\$episodeId")
|
||||
.parsedSafe<LoadLinks>()
|
||||
|
||||
res?.sources?.map { source ->
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
this.name,
|
||||
source.url ?: return@map null,
|
||||
"$mainServerAPI/",
|
||||
getQualityFromName(source.quality),
|
||||
isM3u8 = source.isM3U8,
|
||||
headers = mapOf("Origin" to mainServerAPI)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
suspend fun invokeHDMovieBox(
|
||||
title: String? = null,
|
||||
|
@ -385,11 +363,11 @@ object SoraExtractor : SoraStream() {
|
|||
) {
|
||||
val fixTitle = title.fixTitle()
|
||||
val url = "$hdMovieBoxAPI/watch/$fixTitle"
|
||||
val ref = if (season == null) {
|
||||
"$hdMovieBoxAPI/watch/$fixTitle"
|
||||
} else {
|
||||
"$hdMovieBoxAPI/watch/$fixTitle/season-$season/episode-$episode"
|
||||
}
|
||||
// val ref = if (season == null) {
|
||||
// "$hdMovieBoxAPI/watch/$fixTitle"
|
||||
// } else {
|
||||
// "$hdMovieBoxAPI/watch/$fixTitle/season-$season/episode-$episode"
|
||||
// }
|
||||
|
||||
val doc = app.get(url).document
|
||||
val id = if (season == null) {
|
||||
|
@ -456,7 +434,7 @@ object SoraExtractor : SoraStream() {
|
|||
}
|
||||
|
||||
val request = app.get(url)
|
||||
if(!request.isSuccessful) return
|
||||
if (!request.isSuccessful) return
|
||||
val res = request.document
|
||||
val sources: ArrayList<String?> = arrayListOf()
|
||||
|
||||
|
@ -501,7 +479,7 @@ object SoraExtractor : SoraStream() {
|
|||
}
|
||||
|
||||
val res = app.get(url)
|
||||
if(!res.isSuccessful) return
|
||||
if (!res.isSuccessful) return
|
||||
val document = res.document
|
||||
val id = document.select("meta#dooplay-ajax-counter").attr("data-postid")
|
||||
val type = if (url.contains("/movie/")) "movie" else "tv"
|
||||
|
@ -521,8 +499,8 @@ object SoraExtractor : SoraStream() {
|
|||
referer = url
|
||||
).parsed<ResponseHash>().embed_url
|
||||
|
||||
if(!source.contains("youtube")) {
|
||||
loadExtractor(source, "$idlixAPI/", subtitleCallback, callback)
|
||||
if (!source.contains("youtube")) {
|
||||
loadExtractor(source, "$idlixAPI/", subtitleCallback, callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -543,7 +521,7 @@ object SoraExtractor : SoraStream() {
|
|||
}
|
||||
|
||||
val res = app.get(url)
|
||||
if(!res.isSuccessful) return
|
||||
if (!res.isSuccessful) return
|
||||
val document = res.document
|
||||
val type = if (url.contains("/movie/")) "movie" else "tv"
|
||||
document.select("ul#playeroptionsul > li").apmap { el ->
|
||||
|
@ -570,10 +548,12 @@ object SoraExtractor : SoraStream() {
|
|||
val srcm3u8 = resDoc.selectFirst("script:containsData(let url =)")?.data()?.let {
|
||||
Regex("['|\"](.*?.m3u8)['|\"]").find(it)?.groupValues?.getOrNull(1)
|
||||
} ?: return@apmap null
|
||||
val quality = app.get(srcm3u8, referer = source, headers = mapOf(
|
||||
"Accept" to "*/*",
|
||||
)).text.let { quality ->
|
||||
if(quality.contains("RESOLUTION=1920")) Qualities.P1080.value else Qualities.P720.value
|
||||
val quality = app.get(
|
||||
srcm3u8, referer = source, headers = mapOf(
|
||||
"Accept" to "*/*",
|
||||
)
|
||||
).text.let { quality ->
|
||||
if (quality.contains("RESOLUTION=1920")) Qualities.P1080.value else Qualities.P720.value
|
||||
}
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
|
@ -650,7 +630,8 @@ object SoraExtractor : SoraStream() {
|
|||
} else {
|
||||
"${filmxyAPI}/tv/$imdbId"
|
||||
}
|
||||
val filmxyCookies = getFilmxyCookies(imdbId, season) ?: throw ErrorLoadingException("No Cookies Found")
|
||||
val filmxyCookies =
|
||||
getFilmxyCookies(imdbId, season) ?: throw ErrorLoadingException("No Cookies Found")
|
||||
|
||||
val cookiesDoc = mapOf(
|
||||
"G_ENABLED_IDPS" to "google",
|
||||
|
@ -659,12 +640,13 @@ object SoraExtractor : SoraStream() {
|
|||
)
|
||||
|
||||
val request = session.get(url, cookies = cookiesDoc)
|
||||
if(!request.isSuccessful) return
|
||||
if (!request.isSuccessful) return
|
||||
|
||||
val doc = request.document
|
||||
val script = doc.selectFirst("script:containsData(var isSingle)")?.data().toString()
|
||||
val sourcesData = Regex("listSE\\s*=\\s?(.*?),[\\n|\\s]").find(script)?.groupValues?.get(1)
|
||||
val sourcesDetail = Regex("linkDetails\\s*=\\s?(.*?),[\\n|\\s]").find(script)?.groupValues?.get(1)
|
||||
val sourcesDetail =
|
||||
Regex("linkDetails\\s*=\\s?(.*?),[\\n|\\s]").find(script)?.groupValues?.get(1)
|
||||
|
||||
//Gson is shit, but i don't care
|
||||
val sourcesJson = JsonParser().parse(sourcesData).asJsonObject
|
||||
|
@ -678,9 +660,12 @@ object SoraExtractor : SoraStream() {
|
|||
sourcesJson.getAsJsonObject("s$sson").getAsJsonArray("e$eps")
|
||||
}.asJsonArray
|
||||
|
||||
val scriptUser = doc.select("script").find { it.data().contains("var userNonce") }?.data().toString()
|
||||
val userNonce = Regex("var\\suserNonce.*?[\"|'](\\S+?)[\"|'];").find(scriptUser)?.groupValues?.get(1)
|
||||
val userId = Regex("var\\suser_id.*?[\"|'](\\S+?)[\"|'];").find(scriptUser)?.groupValues?.get(1)
|
||||
val scriptUser =
|
||||
doc.select("script").find { it.data().contains("var userNonce") }?.data().toString()
|
||||
val userNonce =
|
||||
Regex("var\\suserNonce.*?[\"|'](\\S+?)[\"|'];").find(scriptUser)?.groupValues?.get(1)
|
||||
val userId =
|
||||
Regex("var\\suser_id.*?[\"|'](\\S+?)[\"|'];").find(scriptUser)?.groupValues?.get(1)
|
||||
val linkIDs = sources.joinToString("") {
|
||||
"&linkIDs%5B%5D=$it"
|
||||
}.replace("\"", "")
|
||||
|
@ -709,8 +694,10 @@ object SoraExtractor : SoraStream() {
|
|||
sources.map { source ->
|
||||
val src = source.asString
|
||||
val link = json.getAsJsonPrimitive(src).asString
|
||||
val quality = sourcesDetailJson.getAsJsonObject(src).getAsJsonPrimitive("resolution").asString
|
||||
val server = sourcesDetailJson.getAsJsonObject(src).getAsJsonPrimitive("server").asString
|
||||
val quality =
|
||||
sourcesDetailJson.getAsJsonObject(src).getAsJsonPrimitive("resolution").asString
|
||||
val server =
|
||||
sourcesDetailJson.getAsJsonObject(src).getAsJsonPrimitive("server").asString
|
||||
val size = sourcesDetailJson.getAsJsonObject(src).getAsJsonPrimitive("size").asString
|
||||
|
||||
callback.invoke(
|
||||
|
@ -734,7 +721,7 @@ object SoraExtractor : SoraStream() {
|
|||
callback: (ExtractorLink) -> Unit
|
||||
) {
|
||||
val fixTitle = title.fixTitle()
|
||||
val url = if(season == null) {
|
||||
val url = if (season == null) {
|
||||
"$kimcartoonAPI/Cartoon/$fixTitle"
|
||||
} else {
|
||||
"$kimcartoonAPI/Cartoon/$fixTitle-season-$season"
|
||||
|
@ -749,7 +736,9 @@ object SoraExtractor : SoraStream() {
|
|||
}.first { it.contains("Season-$season", true) && it.contains("Episode-$episode", true) }
|
||||
} ?: return
|
||||
|
||||
val source = app.get(fixUrl(iframe, kimcartoonAPI)).document.select("div#divContentVideo iframe").attr("src")
|
||||
val source =
|
||||
app.get(fixUrl(iframe, kimcartoonAPI)).document.select("div#divContentVideo iframe")
|
||||
.attr("src")
|
||||
loadExtractor(source, "$kimcartoonAPI/", subtitleCallback) { link ->
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
|
@ -779,7 +768,8 @@ object SoraExtractor : SoraStream() {
|
|||
"versioncode" to "11",
|
||||
"clienttype" to "ios_jike_default"
|
||||
)
|
||||
val vipAPI = base64DecodeAPI("cA==YXA=cy8=Y20=di8=LnQ=b2s=a2w=bG8=aS4=YXA=ZS0=aWw=b2I=LW0=Z2E=Ly8=czo=dHA=aHQ=")
|
||||
val vipAPI =
|
||||
base64DecodeAPI("cA==YXA=cy8=Y20=di8=LnQ=b2s=a2w=bG8=aS4=YXA=ZS0=aWw=b2I=LW0=Z2E=Ly8=czo=dHA=aHQ=")
|
||||
val vipUrl = base64DecodeAPI("b20=LmM=b2s=a2w=bG8=Ly8=czo=dHA=aHQ=")
|
||||
|
||||
val doc = app.get(
|
||||
|
@ -821,12 +811,14 @@ object SoraExtractor : SoraStream() {
|
|||
headers = headers
|
||||
)
|
||||
|
||||
if(!jsonResponse.isSuccessful) return
|
||||
if (!jsonResponse.isSuccessful) return
|
||||
|
||||
val json = jsonResponse.parsedSafe<Load>()?.data?.episodeVo?.first { it.seriesNo == (episode ?: 0) }
|
||||
val json = jsonResponse.parsedSafe<Load>()?.data?.episodeVo?.first {
|
||||
it.seriesNo == (episode ?: 0)
|
||||
}
|
||||
|
||||
json?.definitionList?.apmap { video ->
|
||||
delay(2000)
|
||||
delay(1000)
|
||||
app.get(
|
||||
"${vipAPI}/media/previewInfo?category=${type}&contentId=${id}&episodeId=${json.id}&definition=${video.code}",
|
||||
headers = headers
|
||||
|
@ -934,33 +926,35 @@ object SoraExtractor : SoraStream() {
|
|||
) {
|
||||
val fixTitle = title?.replace("–", "-")
|
||||
val id =
|
||||
app.get("$consumetFlixhqAPI/$title").parsedSafe<FlixhqSearchResponse>()?.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"
|
||||
}
|
||||
}?.id ?: return
|
||||
app.get("$consumetFlixhqAPI/$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"
|
||||
}
|
||||
}?.id ?: return
|
||||
|
||||
val episodeId = app.get("$consumetFlixhqAPI/info?id=$id").parsedSafe<FlixhqDetails>()?.let {
|
||||
if (season == null) {
|
||||
it.episodes?.first()?.id
|
||||
} else {
|
||||
it.episodes?.find { ep -> ep.number == episode && ep.season == season }?.id
|
||||
}
|
||||
} ?: return
|
||||
val episodeId =
|
||||
app.get("$consumetFlixhqAPI/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
|
||||
|
||||
listOf(
|
||||
"vidcloud",
|
||||
"upcloud"
|
||||
).apmap { server ->
|
||||
delay(2000)
|
||||
delay(1000)
|
||||
val sources =
|
||||
app.get("$consumetFlixhqAPI/watch?episodeId=$episodeId&mediaId=$id&server=$server")
|
||||
.parsedSafe<FlixhqSourcesResponse>()
|
||||
.parsedSafe<ConsumetSourcesResponse>()
|
||||
val name = fixTitle(server)
|
||||
sources?.sources?.map {
|
||||
callback.invoke(
|
||||
|
@ -1052,8 +1046,20 @@ object SoraExtractor : SoraStream() {
|
|||
link?.substringBefore("=http") ?: return@apmap null,
|
||||
"$kissKhAPI/",
|
||||
subtitleCallback,
|
||||
callback
|
||||
)
|
||||
) { links ->
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
"StreamSS",
|
||||
"StreamSS",
|
||||
links.url,
|
||||
links.referer,
|
||||
links.quality,
|
||||
links.isM3u8,
|
||||
links.headers,
|
||||
links.extractorData
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1072,6 +1078,58 @@ object SoraExtractor : SoraStream() {
|
|||
|
||||
}
|
||||
|
||||
suspend fun invoZoro(
|
||||
id: Int? = null,
|
||||
season: Int? = null,
|
||||
episode: Int? = null,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
) {
|
||||
val malId = app.get("$tmdb2mal/?id=$id&s=$season").text.trim()
|
||||
val (engTitle, japTitle) = app.get("https://animixplay.to/assets/mal/$malId.json")
|
||||
.parsedSafe<AnimixData>()?.let {
|
||||
it.title_english to it.title
|
||||
} ?: return
|
||||
|
||||
val animeId =
|
||||
app.get("$consumetZoroAPI/$japTitle").parsedSafe<ConsumetSearchResponse>()?.results?.find {
|
||||
val title = it.title ?: return
|
||||
(title.equals(engTitle, true) || title.equals(japTitle, true) ) && it.type == "TV"
|
||||
}?.id ?: return
|
||||
|
||||
val episodeId = app.get("$consumetZoroAPI/info?id=$animeId")
|
||||
.parsedSafe<ConsumetDetails>()?.episodes?.find {
|
||||
it.number == episode
|
||||
}?.id ?: return
|
||||
|
||||
val sources = app.get("$consumetZoroAPI/watch?episodeId=$episodeId")
|
||||
.parsedSafe<ConsumetSourcesResponse>() ?: return
|
||||
|
||||
sources.sources?.map {
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
"Zoro",
|
||||
"Zoro",
|
||||
it.url ?: return@map null,
|
||||
"",
|
||||
getQualityFromName(it.quality),
|
||||
it.isM3U8 ?: true
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
sources.subtitles?.map {
|
||||
subtitleCallback.invoke(
|
||||
SubtitleFile(
|
||||
it.lang ?: "",
|
||||
it.url ?: return@map null
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data class FilmxyCookies(
|
||||
|
@ -1096,7 +1154,7 @@ suspend fun getFilmxyCookies(imdbId: String? = null, season: Int? = null): Filmx
|
|||
),
|
||||
)
|
||||
|
||||
if(!res.isSuccessful) return FilmxyCookies()
|
||||
if (!res.isSuccessful) return FilmxyCookies()
|
||||
|
||||
val userNonce =
|
||||
res.document.select("script").find { it.data().contains("var userNonce") }?.data()?.let {
|
||||
|
@ -1120,7 +1178,8 @@ suspend fun getFilmxyCookies(imdbId: String? = null, season: Int? = null): Filmx
|
|||
|
||||
val cookieJar = session.baseClient.cookieJar.loadForRequest(cookieUrl.toHttpUrl())
|
||||
phpsessid = cookieJar.first { it.name == "PHPSESSID" }.value
|
||||
val wLog = cookieJar.first { it.name == "wordpress_logged_in_8bf9d5433ac88cc9a3a396d6b154cd01" }.value
|
||||
val wLog =
|
||||
cookieJar.first { it.name == "wordpress_logged_in_8bf9d5433ac88cc9a3a396d6b154cd01" }.value
|
||||
val wSec = cookieJar.first { it.name == "wordpress_sec_8bf9d5433ac88cc9a3a396d6b154cd01" }.value
|
||||
|
||||
return FilmxyCookies(phpsessid, wLog, wSec)
|
||||
|
@ -1289,46 +1348,46 @@ data class Load(
|
|||
@JsonProperty("data") val data: MediaDetail? = null,
|
||||
)
|
||||
|
||||
data class FlixhqHeaders(
|
||||
data class ConsumetHeaders(
|
||||
@JsonProperty("Referer") val referer: String? = null,
|
||||
)
|
||||
|
||||
data class FlixhqSubtitles(
|
||||
data class ConsumetSubtitles(
|
||||
@JsonProperty("url") val url: String? = null,
|
||||
@JsonProperty("lang") val lang: String? = null,
|
||||
)
|
||||
|
||||
data class FlixhqSources(
|
||||
data class ConsumetSources(
|
||||
@JsonProperty("url") val url: String? = null,
|
||||
@JsonProperty("quality") val quality: String? = null,
|
||||
@JsonProperty("isM3U8") val isM3U8: Boolean? = null,
|
||||
)
|
||||
|
||||
data class FlixhqSourcesResponse(
|
||||
@JsonProperty("headers") val headers: FlixhqHeaders? = null,
|
||||
@JsonProperty("sources") val sources: ArrayList<FlixhqSources>? = arrayListOf(),
|
||||
@JsonProperty("subtitles") val subtitles: ArrayList<FlixhqSubtitles>? = arrayListOf(),
|
||||
data class ConsumetSourcesResponse(
|
||||
@JsonProperty("headers") val headers: ConsumetHeaders? = null,
|
||||
@JsonProperty("sources") val sources: ArrayList<ConsumetSources>? = arrayListOf(),
|
||||
@JsonProperty("subtitles") val subtitles: ArrayList<ConsumetSubtitles>? = arrayListOf(),
|
||||
)
|
||||
|
||||
data class FlixhqEpisodes(
|
||||
data class ConsumetEpisodes(
|
||||
@JsonProperty("id") val id: String? = null,
|
||||
@JsonProperty("number") val number: Int? = null,
|
||||
@JsonProperty("season") val season: Int? = null,
|
||||
)
|
||||
|
||||
data class FlixhqDetails(
|
||||
@JsonProperty("episodes") val episodes: ArrayList<FlixhqEpisodes>? = arrayListOf(),
|
||||
data class ConsumetDetails(
|
||||
@JsonProperty("episodes") val episodes: ArrayList<ConsumetEpisodes>? = arrayListOf(),
|
||||
)
|
||||
|
||||
data class FlixhqResults(
|
||||
data class ConsumetResults(
|
||||
@JsonProperty("id") val id: String? = null,
|
||||
@JsonProperty("title") val title: String? = null,
|
||||
@JsonProperty("releaseDate") val releaseDate: String? = null,
|
||||
@JsonProperty("type") val type: String? = null,
|
||||
)
|
||||
|
||||
data class FlixhqSearchResponse(
|
||||
@JsonProperty("results") val results: ArrayList<FlixhqResults>? = arrayListOf(),
|
||||
data class ConsumetSearchResponse(
|
||||
@JsonProperty("results") val results: ArrayList<ConsumetResults>? = arrayListOf(),
|
||||
)
|
||||
|
||||
data class KisskhSources(
|
||||
|
@ -1355,3 +1414,9 @@ data class KisskhResults(
|
|||
@JsonProperty("title") val title: String?,
|
||||
)
|
||||
|
||||
data class AnimixData(
|
||||
@JsonProperty("title") val title: String? = null,
|
||||
@JsonProperty("title_english") val title_english: String? = null,
|
||||
@JsonProperty("title_japanese") val title_japanese: String? = null,
|
||||
)
|
||||
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
package com.hexated
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.hexated.RandomUserAgent.getRandomUserAgent
|
||||
import com.hexated.SoraExtractor.invoKisskh
|
||||
import com.hexated.SoraExtractor.invoke123Movie
|
||||
import com.hexated.SoraExtractor.invokeDbgo
|
||||
import com.hexated.SoraExtractor.invokeFilmxy
|
||||
import com.hexated.SoraExtractor.invokeFlixhq
|
||||
import com.hexated.SoraExtractor.invokeGogo
|
||||
import com.hexated.SoraExtractor.invokeHDMovieBox
|
||||
import com.hexated.SoraExtractor.invokeIdlix
|
||||
import com.hexated.SoraExtractor.invokeKimcartoon
|
||||
|
@ -21,14 +19,12 @@ import com.hexated.SoraExtractor.invokeUniqueStream
|
|||
import com.hexated.SoraExtractor.invokeVidSrc
|
||||
import com.hexated.SoraExtractor.invokeXmovies
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||
import com.lagradost.cloudstream3.metaproviders.TmdbProvider
|
||||
import com.hexated.SoraExtractor.invoZoro
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.Qualities
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
open class SoraStream : TmdbProvider() {
|
||||
|
@ -48,6 +44,8 @@ open class SoraStream : TmdbProvider() {
|
|||
companion object {
|
||||
private const val tmdbAPI = "https://api.themoviedb.org/3"
|
||||
private const val apiKey = "b030404650f279792a8d3287232358e3" // PLEASE DON'T STEAL
|
||||
const val tmdb2mal = "https://tmdb2mal.slidemovies.org"
|
||||
|
||||
val mainAPI = base64DecodeAPI("cHA=LmE=ZWw=cmM=dmU=aC4=dGM=d2E=eHA=Ly8=czo=dHA=aHQ=")
|
||||
var mainServerAPI =
|
||||
base64DecodeAPI("cA==YXA=bC4=Y2U=ZXI=LnY=aWU=b3Y=LW0=cmE=c28=Ly8=czo=dHA=aHQ=")
|
||||
|
@ -67,6 +65,7 @@ open class SoraStream : TmdbProvider() {
|
|||
const val kimcartoonAPI = "https://kimcartoon.li"
|
||||
const val xMovieAPI = "https://xemovies.net"
|
||||
const val consumetFlixhqAPI = "https://api.consumet.org/movies/flixhq"
|
||||
const val consumetZoroAPI = "https://api.consumet.org/anime/zoro"
|
||||
const val kissKhAPI = "https://kisskh.me"
|
||||
|
||||
fun getType(t: String?): TvType {
|
||||
|
@ -157,17 +156,6 @@ open class SoraStream : TmdbProvider() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun Anime.toSearchResponse(): AnimeSearchResponse? {
|
||||
return newAnimeSearchResponse(
|
||||
title?.romaji ?: title?.english ?: title?.native ?: title?.userPreferred ?: return null,
|
||||
Data(aniId = id, malId = malId).toJson(),
|
||||
TvType.Anime
|
||||
) {
|
||||
this.posterUrl = image
|
||||
addSub(totalEpisodes)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val searchResponse = mutableListOf<SearchResponse>()
|
||||
|
||||
|
@ -179,51 +167,12 @@ open class SoraStream : TmdbProvider() {
|
|||
}
|
||||
if (mainResponse?.isNotEmpty() == true) searchResponse.addAll(mainResponse)
|
||||
|
||||
// val animeResponse =
|
||||
// app.get("$mainServerAPI/search/anime/$query?_data=routes/search/anime/\$animeKeyword")
|
||||
// .parsedSafe<SearchAnime>()?.searchResults?.results?.mapNotNull { anime -> anime.toSearchResponse() }
|
||||
// if (animeResponse?.isNotEmpty() == true) searchResponse.addAll(animeResponse)
|
||||
|
||||
return searchResponse
|
||||
}
|
||||
|
||||
private suspend fun loadAnime(aniId: String? = null, malId: Int? = null): LoadResponse? {
|
||||
|
||||
val res = app.get("$mainServerAPI/anime/$aniId/overview?_data=routes/anime/\$animeId")
|
||||
.parsedSafe<DetailAnimeResult>()?.detail ?: throw ErrorLoadingException()
|
||||
|
||||
val episodes = res.episodes?.map { eps ->
|
||||
Episode(
|
||||
LinkData(aniId = aniId, animeId = eps.id).toJson(),
|
||||
name = eps.title,
|
||||
episode = eps.number
|
||||
)
|
||||
}
|
||||
|
||||
return newAnimeLoadResponse(
|
||||
res.title?.romaji ?: res.title?.english ?: res.title?.native ?: res.title?.userPreferred
|
||||
?: return null,
|
||||
"",
|
||||
TvType.Anime
|
||||
) {
|
||||
posterUrl = res.image
|
||||
this.year = res.releaseDate
|
||||
plot = res.description
|
||||
this.tags = res.genres
|
||||
this.recommendations = res.recommendations?.mapNotNull { it.toSearchResponse() }
|
||||
addMalId(malId)
|
||||
addAniListId(aniId?.toIntOrNull())
|
||||
addEpisodes(DubStatus.Subbed, episodes)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
val data = parseJson<Data>(url)
|
||||
|
||||
if (data.aniId?.isNotEmpty() == true) {
|
||||
return loadAnime(data.aniId, data.malId)
|
||||
}
|
||||
|
||||
val buildId =
|
||||
app.get("$mainAPI/").text.substringAfterLast("\"buildId\":\"").substringBefore("\",")
|
||||
val responses =
|
||||
|
@ -327,16 +276,16 @@ open class SoraStream : TmdbProvider() {
|
|||
): Boolean {
|
||||
|
||||
val res = parseJson<LinkData>(data)
|
||||
val query = if (res.type == "tv") {
|
||||
"$mainServerAPI/tv-shows/${res.id}/season/${res.season}/episode/${res.episode}?_data=routes/tv-shows/\$tvId.season.\$seasonId.episode.\$episodeId"
|
||||
} else {
|
||||
"$mainServerAPI/movies/${res.id}/watch?_data=routes/movies/\$movieId.watch"
|
||||
}
|
||||
val referer = if (res.type == "tv") {
|
||||
"$mainServerAPI/tv-shows/${res.id}/season/${res.season}/episode/${res.episode}"
|
||||
} else {
|
||||
"$mainServerAPI/movies/${res.id}/watch"
|
||||
}
|
||||
// val query = if (res.type == "tv") {
|
||||
// "$mainServerAPI/tv-shows/${res.id}/season/${res.season}/episode/${res.episode}?_data=routes/tv-shows/\$tvId.season.\$seasonId.episode.\$episodeId"
|
||||
// } else {
|
||||
// "$mainServerAPI/movies/${res.id}/watch?_data=routes/movies/\$movieId.watch"
|
||||
// }
|
||||
// val referer = if (res.type == "tv") {
|
||||
// "$mainServerAPI/tv-shows/${res.id}/season/${res.season}/episode/${res.episode}"
|
||||
// } else {
|
||||
// "$mainServerAPI/movies/${res.id}/watch"
|
||||
// }
|
||||
|
||||
argamap(
|
||||
{
|
||||
|
@ -349,35 +298,35 @@ open class SoraStream : TmdbProvider() {
|
|||
callback
|
||||
)
|
||||
},
|
||||
{
|
||||
val json = app.get(
|
||||
query,
|
||||
referer = referer,
|
||||
headers = mapOf("User-Agent" to getRandomUserAgent())
|
||||
).parsedSafe<LoadLinks>()
|
||||
|
||||
json?.sources?.map { source ->
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
this.name,
|
||||
source.url ?: return@map null,
|
||||
"$mainServerAPI/",
|
||||
source.quality?.toIntOrNull() ?: Qualities.Unknown.value,
|
||||
isM3u8 = source.isM3U8,
|
||||
headers = mapOf("Origin" to mainServerAPI)
|
||||
)
|
||||
)
|
||||
}
|
||||
json?.subtitles?.map { sub ->
|
||||
subtitleCallback.invoke(
|
||||
SubtitleFile(
|
||||
getLanguage(sub.lang.toString()),
|
||||
sub.url ?: return@map null
|
||||
)
|
||||
)
|
||||
}
|
||||
},
|
||||
// {
|
||||
// val json = app.get(
|
||||
// query,
|
||||
// referer = referer,
|
||||
// headers = mapOf("User-Agent" to getRandomUserAgent())
|
||||
// ).parsedSafe<LoadLinks>()
|
||||
//
|
||||
// json?.sources?.map { source ->
|
||||
// callback.invoke(
|
||||
// ExtractorLink(
|
||||
// this.name,
|
||||
// this.name,
|
||||
// source.url ?: return@map null,
|
||||
// "$mainServerAPI/",
|
||||
// source.quality?.toIntOrNull() ?: Qualities.Unknown.value,
|
||||
// isM3u8 = source.isM3U8,
|
||||
// headers = mapOf("Origin" to mainServerAPI)
|
||||
// )
|
||||
// )
|
||||
// }
|
||||
// json?.subtitles?.map { sub ->
|
||||
// subtitleCallback.invoke(
|
||||
// SubtitleFile(
|
||||
// getLanguage(sub.lang.toString()),
|
||||
// sub.url ?: return@map null
|
||||
// )
|
||||
// )
|
||||
// }
|
||||
// },
|
||||
{
|
||||
invokeTwoEmbed(res.id, res.season, res.episode, subtitleCallback, callback)
|
||||
},
|
||||
|
@ -413,9 +362,11 @@ open class SoraStream : TmdbProvider() {
|
|||
// )
|
||||
// },
|
||||
{
|
||||
if (res.aniId?.isNotEmpty() == true) invokeGogo(
|
||||
res.aniId,
|
||||
res.animeId,
|
||||
if (res.season != null) invoZoro(
|
||||
res.id,
|
||||
res.season,
|
||||
res.episode,
|
||||
subtitleCallback,
|
||||
callback
|
||||
)
|
||||
},
|
||||
|
@ -505,16 +456,6 @@ open class SoraStream : TmdbProvider() {
|
|||
@JsonProperty("subtitles") val subtitles: ArrayList<Subtitles>? = arrayListOf(),
|
||||
)
|
||||
|
||||
data class SourcesVIP(
|
||||
@JsonProperty("url") val url: String? = null,
|
||||
@JsonProperty("quality") val quality: Int? = null,
|
||||
)
|
||||
|
||||
data class LoadVIPLinks(
|
||||
@JsonProperty("sources") val sources: ArrayList<SourcesVIP>? = arrayListOf(),
|
||||
@JsonProperty("subtitles") val subtitles: ArrayList<Subtitles>? = arrayListOf(),
|
||||
)
|
||||
|
||||
data class Results(
|
||||
@JsonProperty("results") val results: ArrayList<Media>? = arrayListOf(),
|
||||
)
|
||||
|
@ -610,81 +551,6 @@ open class SoraStream : TmdbProvider() {
|
|||
@JsonProperty("tracks") val tracks: List<String>? = null,
|
||||
)
|
||||
|
||||
data class TitleAnime(
|
||||
@JsonProperty("romaji") val romaji: String? = null,
|
||||
@JsonProperty("english") val english: String? = null,
|
||||
@JsonProperty("native") val native: String? = null,
|
||||
@JsonProperty("userPreferred") val userPreferred: String? = null,
|
||||
)
|
||||
|
||||
data class Anime(
|
||||
@JsonProperty("title") val title: TitleAnime? = null,
|
||||
@JsonProperty("id") val id: String? = null,
|
||||
@JsonProperty("malId") val malId: Int? = null,
|
||||
@JsonProperty("image") val image: String? = null,
|
||||
@JsonProperty("totalEpisodes") val totalEpisodes: Int? = null,
|
||||
)
|
||||
|
||||
data class SearchResults(
|
||||
@JsonProperty("results") val results: ArrayList<Anime>? = null,
|
||||
)
|
||||
|
||||
data class SearchAnime(
|
||||
@JsonProperty("searchResults") val searchResults: SearchResults? = null,
|
||||
)
|
||||
|
||||
data class TrailerAnime(
|
||||
@JsonProperty("id") val id: String? = null,
|
||||
)
|
||||
|
||||
data class EpisodesAnime(
|
||||
@JsonProperty("id") val id: String? = null,
|
||||
@JsonProperty("title") val title: String? = null,
|
||||
@JsonProperty("number") val number: Int? = null,
|
||||
)
|
||||
|
||||
data class DetailAnime(
|
||||
@JsonProperty("title") val title: TitleAnime? = null,
|
||||
@JsonProperty("id") val aniId: String? = null,
|
||||
@JsonProperty("malId") val malId: Int? = null,
|
||||
@JsonProperty("image") val image: String? = null,
|
||||
@JsonProperty("description") val description: String? = null,
|
||||
@JsonProperty("releaseDate") val releaseDate: Int? = null,
|
||||
@JsonProperty("rating") val rating: Int? = null,
|
||||
@JsonProperty("duration") val duration: Int? = null,
|
||||
@JsonProperty("type") val type: String? = null,
|
||||
@JsonProperty("recommendations") val recommendations: ArrayList<Anime>? = arrayListOf(),
|
||||
@JsonProperty("episodes") val episodes: ArrayList<EpisodesAnime>? = arrayListOf(),
|
||||
@JsonProperty("genres") val genres: ArrayList<String>? = arrayListOf(),
|
||||
@JsonProperty("trailer") val trailer: TrailerAnime? = null,
|
||||
)
|
||||
|
||||
data class DetailAnimeResult(
|
||||
@JsonProperty("detail") val detail: DetailAnime? = null,
|
||||
)
|
||||
|
||||
data class SeasonsVip(
|
||||
@JsonProperty("air_date") val air_date: String? = null,
|
||||
@JsonProperty("season_number") val season_number: Int? = null,
|
||||
)
|
||||
|
||||
data class DataVip(
|
||||
@JsonProperty("id") val id: String? = null,
|
||||
)
|
||||
|
||||
data class DetailVipResult(
|
||||
@JsonProperty("data") val data: DataVip? = null,
|
||||
)
|
||||
|
||||
data class Providers(
|
||||
@JsonProperty("id") val id: String? = null,
|
||||
@JsonProperty("provider") val provider: String? = null,
|
||||
)
|
||||
|
||||
data class ProvidersResult(
|
||||
@JsonProperty("provider") val provider: ArrayList<Providers>? = arrayListOf(),
|
||||
)
|
||||
|
||||
data class MovieHabData(
|
||||
@JsonProperty("link") val link: String? = null,
|
||||
@JsonProperty("token") val token: String? = null,
|
||||
|
|
Loading…
Reference in a new issue