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 | ||||
| version = 8 | ||||
| version = 9 | ||||
| 
 | ||||
| 
 | ||||
| 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 { | ||||
|  | @ -343,3 +379,13 @@ private data class MovieHabData( | |||
| private data class MovieHabRes( | ||||
|     @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.SoraExtractor.invoke123Movie | ||||
| import com.hexated.SoraExtractor.invokeDbgo | ||||
| import com.hexated.SoraExtractor.invokeGogo | ||||
| import com.hexated.SoraExtractor.invokeLocalSources | ||||
| import com.hexated.SoraExtractor.invokeMovieHab | ||||
| import com.hexated.SoraExtractor.invokeOlgply | ||||
| import com.hexated.SoraExtractor.invokeTwoEmbed | ||||
| import com.hexated.SoraExtractor.invokeVidSrc | ||||
| 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.utils.AppUtils.parseJson | ||||
| 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> { | ||||
|         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", | ||||
|             referer = "$mainAPI/" | ||||
|         ).parsedSafe<Results>()?.results?.mapNotNull { media -> | ||||
|             media.toSearchResponse() | ||||
|         } ?: 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? { | ||||
|         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 = | ||||
|  | @ -265,10 +325,20 @@ open class SoraStream : TmdbProvider() { | |||
|                 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) | ||||
|             }, | ||||
|             { | ||||
|                 invokeGogo(res.aniId, res.animeId, callback) | ||||
|             }) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -282,11 +352,15 @@ open class SoraStream : TmdbProvider() { | |||
|         val type: String? = null, | ||||
|         val season: Int? = null, | ||||
|         val episode: Int? = null, | ||||
|         val aniId: String? = null, | ||||
|         val animeId: String? = null, | ||||
|     ) | ||||
| 
 | ||||
|     data class Data( | ||||
|         val id: Int? = null, | ||||
|         val type: String? = null, | ||||
|         val aniId: String? = null, | ||||
|         val malId: Int? = null, | ||||
|     ) | ||||
| 
 | ||||
|     data class Subtitles( | ||||
|  | @ -388,4 +462,57 @@ 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, | ||||
|     ) | ||||
| 
 | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue