added new anime Sources into SoraExtractor

This commit is contained in:
hexated 2022-11-18 18:00:36 +07:00
parent 10cebd58a9
commit 4c9e9555a0
4 changed files with 243 additions and 1975 deletions

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -19,6 +19,7 @@ val session = Session(Requests().baseClient)
object SoraExtractor : SoraStream() { object SoraExtractor : SoraStream() {
/*
suspend fun invokeLocalSources( suspend fun invokeLocalSources(
url: String, url: String,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,
@ -56,6 +57,7 @@ object SoraExtractor : SoraStream() {
} }
} }
*/
suspend fun invokeTwoEmbed( suspend fun invokeTwoEmbed(
id: Int? = null, id: Int? = null,
@ -303,79 +305,55 @@ object SoraExtractor : SoraStream() {
loadExtractor(url, databaseGdriveAPI, subtitleCallback, callback) loadExtractor(url, databaseGdriveAPI, subtitleCallback, callback)
} }
/* suspend fun invokeSoraVIP( /* suspend fun invokeSoraVIP(
title: String? = null, title: String? = null,
orgTitle: String? = null, orgTitle: String? = null,
year: Int? = null, year: Int? = null,
season: Int? = null, season: Int? = null,
episode: Int? = null, episode: Int? = null,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
) { ) {
val apiUrl = base64DecodeAPI("aQ==YXA=cC8=YXA=bC4=Y2U=ZXI=LnY=b2s=a2w=bG8=Ly8=czo=dHA=aHQ=") val apiUrl = base64DecodeAPI("aQ==YXA=cC8=YXA=bC4=Y2U=ZXI=LnY=b2s=a2w=bG8=Ly8=czo=dHA=aHQ=")
val url = if(season == null) { val url = if(season == null) {
"$apiUrl/search/one?title=$title&orgTitle=$orgTitle&year=$year" "$apiUrl/search/one?title=$title&orgTitle=$orgTitle&year=$year"
} else { } else {
"$apiUrl/search/one?title=$title&orgTitle=$orgTitle&year=$year&season=$season" "$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) { val sourcesUrl = if(season == null) {
"$apiUrl/movie/detail?id=$id" "$apiUrl/movie/detail?id=$id"
} else { } else {
"$apiUrl/tv/detail?id=$id&episodeId=${episode?.minus(1)}" "$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 -> json?.sources?.map { source ->
callback.invoke( callback.invoke(
ExtractorLink( ExtractorLink(
"${this.name} (VIP)", "${this.name} (VIP)",
"${this.name} (VIP)", "${this.name} (VIP)",
source.url ?: return@map null, source.url ?: return@map null,
"$apiUrl/", "$apiUrl/",
source.quality ?: Qualities.Unknown.value, source.quality ?: Qualities.Unknown.value,
isM3u8 = source.url.contains(".m3u8"), isM3u8 = source.url.contains(".m3u8"),
)
) )
) }
}
json?.subtitles?.map { sub -> json?.subtitles?.map { sub ->
subtitleCallback.invoke( subtitleCallback.invoke(
SubtitleFile( SubtitleFile(
getLanguage(sub.language.toString()), getLanguage(sub.language.toString()),
sub.url ?: return@map null 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( suspend fun invokeHDMovieBox(
title: String? = null, title: String? = null,
@ -385,11 +363,11 @@ object SoraExtractor : SoraStream() {
) { ) {
val fixTitle = title.fixTitle() val fixTitle = title.fixTitle()
val url = "$hdMovieBoxAPI/watch/$fixTitle" val url = "$hdMovieBoxAPI/watch/$fixTitle"
val ref = if (season == null) { // val ref = if (season == null) {
"$hdMovieBoxAPI/watch/$fixTitle" // "$hdMovieBoxAPI/watch/$fixTitle"
} else { // } else {
"$hdMovieBoxAPI/watch/$fixTitle/season-$season/episode-$episode" // "$hdMovieBoxAPI/watch/$fixTitle/season-$season/episode-$episode"
} // }
val doc = app.get(url).document val doc = app.get(url).document
val id = if (season == null) { val id = if (season == null) {
@ -456,7 +434,7 @@ object SoraExtractor : SoraStream() {
} }
val request = app.get(url) val request = app.get(url)
if(!request.isSuccessful) return if (!request.isSuccessful) return
val res = request.document val res = request.document
val sources: ArrayList<String?> = arrayListOf() val sources: ArrayList<String?> = arrayListOf()
@ -501,7 +479,7 @@ object SoraExtractor : SoraStream() {
} }
val res = app.get(url) val res = app.get(url)
if(!res.isSuccessful) return if (!res.isSuccessful) return
val document = res.document val document = res.document
val id = document.select("meta#dooplay-ajax-counter").attr("data-postid") val id = document.select("meta#dooplay-ajax-counter").attr("data-postid")
val type = if (url.contains("/movie/")) "movie" else "tv" val type = if (url.contains("/movie/")) "movie" else "tv"
@ -521,8 +499,8 @@ object SoraExtractor : SoraStream() {
referer = url referer = url
).parsed<ResponseHash>().embed_url ).parsed<ResponseHash>().embed_url
if(!source.contains("youtube")) { if (!source.contains("youtube")) {
loadExtractor(source, "$idlixAPI/", subtitleCallback, callback) loadExtractor(source, "$idlixAPI/", subtitleCallback, callback)
} }
} }
} }
@ -543,7 +521,7 @@ object SoraExtractor : SoraStream() {
} }
val res = app.get(url) val res = app.get(url)
if(!res.isSuccessful) return if (!res.isSuccessful) return
val document = res.document val document = res.document
val type = if (url.contains("/movie/")) "movie" else "tv" val type = if (url.contains("/movie/")) "movie" else "tv"
document.select("ul#playeroptionsul > li").apmap { el -> document.select("ul#playeroptionsul > li").apmap { el ->
@ -570,10 +548,12 @@ object SoraExtractor : SoraStream() {
val srcm3u8 = resDoc.selectFirst("script:containsData(let url =)")?.data()?.let { val srcm3u8 = resDoc.selectFirst("script:containsData(let url =)")?.data()?.let {
Regex("['|\"](.*?.m3u8)['|\"]").find(it)?.groupValues?.getOrNull(1) Regex("['|\"](.*?.m3u8)['|\"]").find(it)?.groupValues?.getOrNull(1)
} ?: return@apmap null } ?: return@apmap null
val quality = app.get(srcm3u8, referer = source, headers = mapOf( val quality = app.get(
"Accept" to "*/*", srcm3u8, referer = source, headers = mapOf(
)).text.let { quality -> "Accept" to "*/*",
if(quality.contains("RESOLUTION=1920")) Qualities.P1080.value else Qualities.P720.value )
).text.let { quality ->
if (quality.contains("RESOLUTION=1920")) Qualities.P1080.value else Qualities.P720.value
} }
callback.invoke( callback.invoke(
ExtractorLink( ExtractorLink(
@ -650,7 +630,8 @@ object SoraExtractor : SoraStream() {
} else { } else {
"${filmxyAPI}/tv/$imdbId" "${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( val cookiesDoc = mapOf(
"G_ENABLED_IDPS" to "google", "G_ENABLED_IDPS" to "google",
@ -659,12 +640,13 @@ object SoraExtractor : SoraStream() {
) )
val request = session.get(url, cookies = cookiesDoc) val request = session.get(url, cookies = cookiesDoc)
if(!request.isSuccessful) return if (!request.isSuccessful) return
val doc = request.document val doc = request.document
val script = doc.selectFirst("script:containsData(var isSingle)")?.data().toString() val script = doc.selectFirst("script:containsData(var isSingle)")?.data().toString()
val sourcesData = Regex("listSE\\s*=\\s?(.*?),[\\n|\\s]").find(script)?.groupValues?.get(1) 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 //Gson is shit, but i don't care
val sourcesJson = JsonParser().parse(sourcesData).asJsonObject val sourcesJson = JsonParser().parse(sourcesData).asJsonObject
@ -678,9 +660,12 @@ object SoraExtractor : SoraStream() {
sourcesJson.getAsJsonObject("s$sson").getAsJsonArray("e$eps") sourcesJson.getAsJsonObject("s$sson").getAsJsonArray("e$eps")
}.asJsonArray }.asJsonArray
val scriptUser = doc.select("script").find { it.data().contains("var userNonce") }?.data().toString() val scriptUser =
val userNonce = Regex("var\\suserNonce.*?[\"|'](\\S+?)[\"|'];").find(scriptUser)?.groupValues?.get(1) doc.select("script").find { it.data().contains("var userNonce") }?.data().toString()
val userId = Regex("var\\suser_id.*?[\"|'](\\S+?)[\"|'];").find(scriptUser)?.groupValues?.get(1) 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("") { val linkIDs = sources.joinToString("") {
"&linkIDs%5B%5D=$it" "&linkIDs%5B%5D=$it"
}.replace("\"", "") }.replace("\"", "")
@ -709,8 +694,10 @@ object SoraExtractor : SoraStream() {
sources.map { source -> sources.map { source ->
val src = source.asString val src = source.asString
val link = json.getAsJsonPrimitive(src).asString val link = json.getAsJsonPrimitive(src).asString
val quality = sourcesDetailJson.getAsJsonObject(src).getAsJsonPrimitive("resolution").asString val quality =
val server = sourcesDetailJson.getAsJsonObject(src).getAsJsonPrimitive("server").asString sourcesDetailJson.getAsJsonObject(src).getAsJsonPrimitive("resolution").asString
val server =
sourcesDetailJson.getAsJsonObject(src).getAsJsonPrimitive("server").asString
val size = sourcesDetailJson.getAsJsonObject(src).getAsJsonPrimitive("size").asString val size = sourcesDetailJson.getAsJsonObject(src).getAsJsonPrimitive("size").asString
callback.invoke( callback.invoke(
@ -734,7 +721,7 @@ object SoraExtractor : SoraStream() {
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
) { ) {
val fixTitle = title.fixTitle() val fixTitle = title.fixTitle()
val url = if(season == null) { val url = if (season == null) {
"$kimcartoonAPI/Cartoon/$fixTitle" "$kimcartoonAPI/Cartoon/$fixTitle"
} else { } else {
"$kimcartoonAPI/Cartoon/$fixTitle-season-$season" "$kimcartoonAPI/Cartoon/$fixTitle-season-$season"
@ -749,7 +736,9 @@ object SoraExtractor : SoraStream() {
}.first { it.contains("Season-$season", true) && it.contains("Episode-$episode", true) } }.first { it.contains("Season-$season", true) && it.contains("Episode-$episode", true) }
} ?: return } ?: 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 -> loadExtractor(source, "$kimcartoonAPI/", subtitleCallback) { link ->
callback.invoke( callback.invoke(
ExtractorLink( ExtractorLink(
@ -779,7 +768,8 @@ object SoraExtractor : SoraStream() {
"versioncode" to "11", "versioncode" to "11",
"clienttype" to "ios_jike_default" "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 vipUrl = base64DecodeAPI("b20=LmM=b2s=a2w=bG8=Ly8=czo=dHA=aHQ=")
val doc = app.get( val doc = app.get(
@ -821,12 +811,14 @@ object SoraExtractor : SoraStream() {
headers = headers 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 -> json?.definitionList?.apmap { video ->
delay(2000) delay(1000)
app.get( app.get(
"${vipAPI}/media/previewInfo?category=${type}&contentId=${id}&episodeId=${json.id}&definition=${video.code}", "${vipAPI}/media/previewInfo?category=${type}&contentId=${id}&episodeId=${json.id}&definition=${video.code}",
headers = headers headers = headers
@ -934,33 +926,35 @@ object SoraExtractor : SoraStream() {
) { ) {
val fixTitle = title?.replace("", "-") val fixTitle = title?.replace("", "-")
val id = val id =
app.get("$consumetFlixhqAPI/$title").parsedSafe<FlixhqSearchResponse>()?.results?.find { app.get("$consumetFlixhqAPI/$title")
if (season == null) { .parsedSafe<ConsumetSearchResponse>()?.results?.find {
it.title?.equals( if (season == null) {
"$fixTitle", it.title?.equals(
true "$fixTitle",
) == true && it.releaseDate?.equals("$year") == true && it.type == "Movie" true
} else { ) == true && it.releaseDate?.equals("$year") == true && it.type == "Movie"
it.title?.equals("$fixTitle", true) == true && it.type == "TV Series" } else {
} it.title?.equals("$fixTitle", true) == true && it.type == "TV Series"
}?.id ?: return }
}?.id ?: return
val episodeId = app.get("$consumetFlixhqAPI/info?id=$id").parsedSafe<FlixhqDetails>()?.let { val episodeId =
if (season == null) { app.get("$consumetFlixhqAPI/info?id=$id").parsedSafe<ConsumetDetails>()?.let {
it.episodes?.first()?.id if (season == null) {
} else { it.episodes?.first()?.id
it.episodes?.find { ep -> ep.number == episode && ep.season == season }?.id } else {
} it.episodes?.find { ep -> ep.number == episode && ep.season == season }?.id
} ?: return }
} ?: return
listOf( listOf(
"vidcloud", "vidcloud",
"upcloud" "upcloud"
).apmap { server -> ).apmap { server ->
delay(2000) delay(1000)
val sources = val sources =
app.get("$consumetFlixhqAPI/watch?episodeId=$episodeId&mediaId=$id&server=$server") app.get("$consumetFlixhqAPI/watch?episodeId=$episodeId&mediaId=$id&server=$server")
.parsedSafe<FlixhqSourcesResponse>() .parsedSafe<ConsumetSourcesResponse>()
val name = fixTitle(server) val name = fixTitle(server)
sources?.sources?.map { sources?.sources?.map {
callback.invoke( callback.invoke(
@ -1052,8 +1046,20 @@ object SoraExtractor : SoraStream() {
link?.substringBefore("=http") ?: return@apmap null, link?.substringBefore("=http") ?: return@apmap null,
"$kissKhAPI/", "$kissKhAPI/",
subtitleCallback, 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( 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 = val userNonce =
res.document.select("script").find { it.data().contains("var userNonce") }?.data()?.let { 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()) val cookieJar = session.baseClient.cookieJar.loadForRequest(cookieUrl.toHttpUrl())
phpsessid = cookieJar.first { it.name == "PHPSESSID" }.value 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 val wSec = cookieJar.first { it.name == "wordpress_sec_8bf9d5433ac88cc9a3a396d6b154cd01" }.value
return FilmxyCookies(phpsessid, wLog, wSec) return FilmxyCookies(phpsessid, wLog, wSec)
@ -1289,46 +1348,46 @@ data class Load(
@JsonProperty("data") val data: MediaDetail? = null, @JsonProperty("data") val data: MediaDetail? = null,
) )
data class FlixhqHeaders( data class ConsumetHeaders(
@JsonProperty("Referer") val referer: String? = null, @JsonProperty("Referer") val referer: String? = null,
) )
data class FlixhqSubtitles( data class ConsumetSubtitles(
@JsonProperty("url") val url: String? = null, @JsonProperty("url") val url: String? = null,
@JsonProperty("lang") val lang: String? = null, @JsonProperty("lang") val lang: String? = null,
) )
data class FlixhqSources( data class ConsumetSources(
@JsonProperty("url") val url: String? = null, @JsonProperty("url") val url: String? = null,
@JsonProperty("quality") val quality: String? = null, @JsonProperty("quality") val quality: String? = null,
@JsonProperty("isM3U8") val isM3U8: Boolean? = null, @JsonProperty("isM3U8") val isM3U8: Boolean? = null,
) )
data class FlixhqSourcesResponse( data class ConsumetSourcesResponse(
@JsonProperty("headers") val headers: FlixhqHeaders? = null, @JsonProperty("headers") val headers: ConsumetHeaders? = null,
@JsonProperty("sources") val sources: ArrayList<FlixhqSources>? = arrayListOf(), @JsonProperty("sources") val sources: ArrayList<ConsumetSources>? = arrayListOf(),
@JsonProperty("subtitles") val subtitles: ArrayList<FlixhqSubtitles>? = arrayListOf(), @JsonProperty("subtitles") val subtitles: ArrayList<ConsumetSubtitles>? = arrayListOf(),
) )
data class FlixhqEpisodes( data class ConsumetEpisodes(
@JsonProperty("id") val id: String? = null, @JsonProperty("id") val id: String? = null,
@JsonProperty("number") val number: Int? = null, @JsonProperty("number") val number: Int? = null,
@JsonProperty("season") val season: Int? = null, @JsonProperty("season") val season: Int? = null,
) )
data class FlixhqDetails( data class ConsumetDetails(
@JsonProperty("episodes") val episodes: ArrayList<FlixhqEpisodes>? = arrayListOf(), @JsonProperty("episodes") val episodes: ArrayList<ConsumetEpisodes>? = arrayListOf(),
) )
data class FlixhqResults( data class ConsumetResults(
@JsonProperty("id") val id: String? = null, @JsonProperty("id") val id: String? = null,
@JsonProperty("title") val title: String? = null, @JsonProperty("title") val title: String? = null,
@JsonProperty("releaseDate") val releaseDate: String? = null, @JsonProperty("releaseDate") val releaseDate: String? = null,
@JsonProperty("type") val type: String? = null, @JsonProperty("type") val type: String? = null,
) )
data class FlixhqSearchResponse( data class ConsumetSearchResponse(
@JsonProperty("results") val results: ArrayList<FlixhqResults>? = arrayListOf(), @JsonProperty("results") val results: ArrayList<ConsumetResults>? = arrayListOf(),
) )
data class KisskhSources( data class KisskhSources(
@ -1355,3 +1414,9 @@ data class KisskhResults(
@JsonProperty("title") val title: String?, @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,
)

View File

@ -1,13 +1,11 @@
package com.hexated package com.hexated
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.hexated.RandomUserAgent.getRandomUserAgent
import com.hexated.SoraExtractor.invoKisskh import com.hexated.SoraExtractor.invoKisskh
import com.hexated.SoraExtractor.invoke123Movie import com.hexated.SoraExtractor.invoke123Movie
import com.hexated.SoraExtractor.invokeDbgo import com.hexated.SoraExtractor.invokeDbgo
import com.hexated.SoraExtractor.invokeFilmxy import com.hexated.SoraExtractor.invokeFilmxy
import com.hexated.SoraExtractor.invokeFlixhq import com.hexated.SoraExtractor.invokeFlixhq
import com.hexated.SoraExtractor.invokeGogo
import com.hexated.SoraExtractor.invokeHDMovieBox import com.hexated.SoraExtractor.invokeHDMovieBox
import com.hexated.SoraExtractor.invokeIdlix import com.hexated.SoraExtractor.invokeIdlix
import com.hexated.SoraExtractor.invokeKimcartoon import com.hexated.SoraExtractor.invokeKimcartoon
@ -21,14 +19,12 @@ import com.hexated.SoraExtractor.invokeUniqueStream
import com.hexated.SoraExtractor.invokeVidSrc import com.hexated.SoraExtractor.invokeVidSrc
import com.hexated.SoraExtractor.invokeXmovies import com.hexated.SoraExtractor.invokeXmovies
import com.lagradost.cloudstream3.* 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.LoadResponse.Companion.addTrailer
import com.lagradost.cloudstream3.metaproviders.TmdbProvider import com.lagradost.cloudstream3.metaproviders.TmdbProvider
import com.hexated.SoraExtractor.invoZoro
import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.AppUtils.parseJson
import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.AppUtils.toJson
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities
import kotlin.math.roundToInt import kotlin.math.roundToInt
open class SoraStream : TmdbProvider() { open class SoraStream : TmdbProvider() {
@ -48,6 +44,8 @@ open class SoraStream : TmdbProvider() {
companion object { companion object {
private const val tmdbAPI = "https://api.themoviedb.org/3" private const val tmdbAPI = "https://api.themoviedb.org/3"
private const val apiKey = "b030404650f279792a8d3287232358e3" // PLEASE DON'T STEAL 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=") val mainAPI = base64DecodeAPI("cHA=LmE=ZWw=cmM=dmU=aC4=dGM=d2E=eHA=Ly8=czo=dHA=aHQ=")
var mainServerAPI = var mainServerAPI =
base64DecodeAPI("cA==YXA=bC4=Y2U=ZXI=LnY=aWU=b3Y=LW0=cmE=c28=Ly8=czo=dHA=aHQ=") 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 kimcartoonAPI = "https://kimcartoon.li"
const val xMovieAPI = "https://xemovies.net" const val xMovieAPI = "https://xemovies.net"
const val consumetFlixhqAPI = "https://api.consumet.org/movies/flixhq" const val consumetFlixhqAPI = "https://api.consumet.org/movies/flixhq"
const val consumetZoroAPI = "https://api.consumet.org/anime/zoro"
const val kissKhAPI = "https://kisskh.me" const val kissKhAPI = "https://kisskh.me"
fun getType(t: String?): TvType { 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> { override suspend fun search(query: String): List<SearchResponse> {
val searchResponse = mutableListOf<SearchResponse>() val searchResponse = mutableListOf<SearchResponse>()
@ -179,51 +167,12 @@ open class SoraStream : TmdbProvider() {
} }
if (mainResponse?.isNotEmpty() == true) searchResponse.addAll(mainResponse) 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 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? { override suspend fun load(url: String): LoadResponse? {
val data = parseJson<Data>(url) val data = parseJson<Data>(url)
if (data.aniId?.isNotEmpty() == true) {
return loadAnime(data.aniId, data.malId)
}
val buildId = val buildId =
app.get("$mainAPI/").text.substringAfterLast("\"buildId\":\"").substringBefore("\",") app.get("$mainAPI/").text.substringAfterLast("\"buildId\":\"").substringBefore("\",")
val responses = val responses =
@ -327,16 +276,16 @@ open class SoraStream : TmdbProvider() {
): Boolean { ): Boolean {
val res = parseJson<LinkData>(data) val res = parseJson<LinkData>(data)
val query = if (res.type == "tv") { // 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" // "$mainServerAPI/tv-shows/${res.id}/season/${res.season}/episode/${res.episode}?_data=routes/tv-shows/\$tvId.season.\$seasonId.episode.\$episodeId"
} else { // } else {
"$mainServerAPI/movies/${res.id}/watch?_data=routes/movies/\$movieId.watch" // "$mainServerAPI/movies/${res.id}/watch?_data=routes/movies/\$movieId.watch"
} // }
val referer = if (res.type == "tv") { // val referer = if (res.type == "tv") {
"$mainServerAPI/tv-shows/${res.id}/season/${res.season}/episode/${res.episode}" // "$mainServerAPI/tv-shows/${res.id}/season/${res.season}/episode/${res.episode}"
} else { // } else {
"$mainServerAPI/movies/${res.id}/watch" // "$mainServerAPI/movies/${res.id}/watch"
} // }
argamap( argamap(
{ {
@ -349,35 +298,35 @@ open class SoraStream : TmdbProvider() {
callback callback
) )
}, },
{ // {
val json = app.get( // val json = app.get(
query, // query,
referer = referer, // referer = referer,
headers = mapOf("User-Agent" to getRandomUserAgent()) // headers = mapOf("User-Agent" to getRandomUserAgent())
).parsedSafe<LoadLinks>() // ).parsedSafe<LoadLinks>()
//
json?.sources?.map { source -> // json?.sources?.map { source ->
callback.invoke( // callback.invoke(
ExtractorLink( // ExtractorLink(
this.name, // this.name,
this.name, // this.name,
source.url ?: return@map null, // source.url ?: return@map null,
"$mainServerAPI/", // "$mainServerAPI/",
source.quality?.toIntOrNull() ?: Qualities.Unknown.value, // source.quality?.toIntOrNull() ?: Qualities.Unknown.value,
isM3u8 = source.isM3U8, // isM3u8 = source.isM3U8,
headers = mapOf("Origin" to mainServerAPI) // headers = mapOf("Origin" to mainServerAPI)
) // )
) // )
} // }
json?.subtitles?.map { sub -> // json?.subtitles?.map { sub ->
subtitleCallback.invoke( // subtitleCallback.invoke(
SubtitleFile( // SubtitleFile(
getLanguage(sub.lang.toString()), // getLanguage(sub.lang.toString()),
sub.url ?: return@map null // sub.url ?: return@map null
) // )
) // )
} // }
}, // },
{ {
invokeTwoEmbed(res.id, res.season, res.episode, subtitleCallback, callback) invokeTwoEmbed(res.id, res.season, res.episode, subtitleCallback, callback)
}, },
@ -413,9 +362,11 @@ open class SoraStream : TmdbProvider() {
// ) // )
// }, // },
{ {
if (res.aniId?.isNotEmpty() == true) invokeGogo( if (res.season != null) invoZoro(
res.aniId, res.id,
res.animeId, res.season,
res.episode,
subtitleCallback,
callback callback
) )
}, },
@ -505,16 +456,6 @@ open class SoraStream : TmdbProvider() {
@JsonProperty("subtitles") val subtitles: ArrayList<Subtitles>? = arrayListOf(), @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( data class Results(
@JsonProperty("results") val results: ArrayList<Media>? = arrayListOf(), @JsonProperty("results") val results: ArrayList<Media>? = arrayListOf(),
) )
@ -610,81 +551,6 @@ open class SoraStream : TmdbProvider() {
@JsonProperty("tracks") val tracks: List<String>? = null, @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( data class MovieHabData(
@JsonProperty("link") val link: String? = null, @JsonProperty("link") val link: String? = null,
@JsonProperty("token") val token: String? = null, @JsonProperty("token") val token: String? = null,