mirror of
https://github.com/hexated/cloudstream-extensions-hexated.git
synced 2024-08-15 00:03:22 +00:00
added Anime support in SoraStream
This commit is contained in:
parent
eee78d4b67
commit
00532d061e
3 changed files with 176 additions and 3 deletions
|
@ -1,5 +1,5 @@
|
||||||
// use an integer for version numbers
|
// use an integer for version numbers
|
||||||
version = 8
|
version = 9
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
cloudstream {
|
||||||
|
|
|
@ -261,6 +261,42 @@ object SoraExtractor : SoraStream() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// suspend fun invokeOpenvids(
|
||||||
|
// id: Int? = null,
|
||||||
|
// season: Int? = null,
|
||||||
|
// episode: Int? = null,
|
||||||
|
// subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
|
// callback: (ExtractorLink) -> Unit
|
||||||
|
// ) {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
|
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)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getQuality(str: String): Int {
|
private fun getQuality(str: String): Int {
|
||||||
|
@ -343,3 +379,13 @@ private data class MovieHabData(
|
||||||
private data class MovieHabRes(
|
private data class MovieHabRes(
|
||||||
@JsonProperty("data") val data: MovieHabData? = null,
|
@JsonProperty("data") val data: MovieHabData? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private data class Sources(
|
||||||
|
@JsonProperty("url") val url: String? = null,
|
||||||
|
@JsonProperty("quality") val quality: String? = null,
|
||||||
|
@JsonProperty("isM3U8") val isM3U8: Boolean = true,
|
||||||
|
)
|
||||||
|
|
||||||
|
private data class LoadLinks(
|
||||||
|
@JsonProperty("sources") val sources: ArrayList<Sources>? = arrayListOf(),
|
||||||
|
)
|
|
@ -4,12 +4,15 @@ import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
import com.hexated.RandomUserAgent.getRandomUserAgent
|
import com.hexated.RandomUserAgent.getRandomUserAgent
|
||||||
import com.hexated.SoraExtractor.invoke123Movie
|
import com.hexated.SoraExtractor.invoke123Movie
|
||||||
import com.hexated.SoraExtractor.invokeDbgo
|
import com.hexated.SoraExtractor.invokeDbgo
|
||||||
|
import com.hexated.SoraExtractor.invokeGogo
|
||||||
import com.hexated.SoraExtractor.invokeLocalSources
|
import com.hexated.SoraExtractor.invokeLocalSources
|
||||||
import com.hexated.SoraExtractor.invokeMovieHab
|
import com.hexated.SoraExtractor.invokeMovieHab
|
||||||
import com.hexated.SoraExtractor.invokeOlgply
|
import com.hexated.SoraExtractor.invokeOlgply
|
||||||
import com.hexated.SoraExtractor.invokeTwoEmbed
|
import com.hexated.SoraExtractor.invokeTwoEmbed
|
||||||
import com.hexated.SoraExtractor.invokeVidSrc
|
import com.hexated.SoraExtractor.invokeVidSrc
|
||||||
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.metaproviders.TmdbProvider
|
import com.lagradost.cloudstream3.metaproviders.TmdbProvider
|
||||||
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
|
||||||
|
@ -106,17 +109,74 @@ 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> {
|
||||||
return app.get(
|
val searchResponse = mutableListOf<SearchResponse>()
|
||||||
|
|
||||||
|
val mainResponse = app.get(
|
||||||
"$tmdbAPI/search/multi?api_key=$apiKey&language=en-US&query=$query&page=1&include_adult=false",
|
"$tmdbAPI/search/multi?api_key=$apiKey&language=en-US&query=$query&page=1&include_adult=false",
|
||||||
referer = "$mainAPI/"
|
referer = "$mainAPI/"
|
||||||
).parsedSafe<Results>()?.results?.mapNotNull { media ->
|
).parsedSafe<Results>()?.results?.mapNotNull { media ->
|
||||||
media.toSearchResponse()
|
media.toSearchResponse()
|
||||||
} ?: throw ErrorLoadingException("Invalid Json reponse")
|
} ?: throw ErrorLoadingException("Invalid Json reponse")
|
||||||
|
searchResponse.addAll(mainResponse)
|
||||||
|
|
||||||
|
val animeResponse =
|
||||||
|
app.get("$mainServerAPI/search/anime/$query?_data=routes/search/anime/\$animeKeyword")
|
||||||
|
.parsedSafe<SearchAnime>()?.searchResults?.results?.mapNotNull { anime -> anime.toSearchResponse() }
|
||||||
|
?: throw ErrorLoadingException("Invalid Json reponse")
|
||||||
|
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? {
|
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 =
|
||||||
|
@ -265,10 +325,20 @@ open class SoraStream : TmdbProvider() {
|
||||||
invokeDbgo(res.imdbId, res.season, res.episode, subtitleCallback, callback)
|
invokeDbgo(res.imdbId, res.season, res.episode, subtitleCallback, callback)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
invoke123Movie(res.id, res.imdbId, res.season, res.episode, subtitleCallback, callback)
|
invoke123Movie(
|
||||||
|
res.id,
|
||||||
|
res.imdbId,
|
||||||
|
res.season,
|
||||||
|
res.episode,
|
||||||
|
subtitleCallback,
|
||||||
|
callback
|
||||||
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
invokeMovieHab(res.id, res.season, res.episode, subtitleCallback, callback)
|
invokeMovieHab(res.id, res.season, res.episode, subtitleCallback, callback)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
invokeGogo(res.aniId, res.animeId, callback)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@ -282,11 +352,15 @@ open class SoraStream : TmdbProvider() {
|
||||||
val type: String? = null,
|
val type: String? = null,
|
||||||
val season: Int? = null,
|
val season: Int? = null,
|
||||||
val episode: Int? = null,
|
val episode: Int? = null,
|
||||||
|
val aniId: String? = null,
|
||||||
|
val animeId: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
data class Data(
|
data class Data(
|
||||||
val id: Int? = null,
|
val id: Int? = null,
|
||||||
val type: String? = null,
|
val type: String? = null,
|
||||||
|
val aniId: String? = null,
|
||||||
|
val malId: Int? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
data class Subtitles(
|
data class Subtitles(
|
||||||
|
@ -388,4 +462,57 @@ 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,
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue