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
4f629f48ec
commit
9ec65f3b24
4 changed files with 243 additions and 1975 deletions
|
@ -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
|
@ -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,
|
||||||
|
@ -352,30 +354,6 @@ object SoraExtractor : SoraStream() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
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) {
|
||||||
|
@ -570,9 +548,11 @@ 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(
|
||||||
|
srcm3u8, referer = source, headers = mapOf(
|
||||||
"Accept" to "*/*",
|
"Accept" to "*/*",
|
||||||
)).text.let { quality ->
|
)
|
||||||
|
).text.let { quality ->
|
||||||
if (quality.contains("RESOLUTION=1920")) Qualities.P1080.value else Qualities.P720.value
|
if (quality.contains("RESOLUTION=1920")) Qualities.P1080.value else Qualities.P720.value
|
||||||
}
|
}
|
||||||
callback.invoke(
|
callback.invoke(
|
||||||
|
@ -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",
|
||||||
|
@ -664,7 +645,8 @@ object SoraExtractor : SoraStream() {
|
||||||
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(
|
||||||
|
@ -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(
|
||||||
|
@ -823,10 +813,12 @@ object SoraExtractor : SoraStream() {
|
||||||
|
|
||||||
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,7 +926,8 @@ 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")
|
||||||
|
.parsedSafe<ConsumetSearchResponse>()?.results?.find {
|
||||||
if (season == null) {
|
if (season == null) {
|
||||||
it.title?.equals(
|
it.title?.equals(
|
||||||
"$fixTitle",
|
"$fixTitle",
|
||||||
|
@ -945,7 +938,8 @@ object SoraExtractor : SoraStream() {
|
||||||
}
|
}
|
||||||
}?.id ?: return
|
}?.id ?: return
|
||||||
|
|
||||||
val episodeId = app.get("$consumetFlixhqAPI/info?id=$id").parsedSafe<FlixhqDetails>()?.let {
|
val episodeId =
|
||||||
|
app.get("$consumetFlixhqAPI/info?id=$id").parsedSafe<ConsumetDetails>()?.let {
|
||||||
if (season == null) {
|
if (season == null) {
|
||||||
it.episodes?.first()?.id
|
it.episodes?.first()?.id
|
||||||
} else {
|
} else {
|
||||||
|
@ -957,10 +951,10 @@ object SoraExtractor : SoraStream() {
|
||||||
"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(
|
||||||
|
@ -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,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue