mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	dubbedanime provider
This commit is contained in:
		
							parent
							
								
									9e434030a4
								
							
						
					
					
						commit
						9e67291a8f
					
				
					 8 changed files with 221 additions and 36 deletions
				
			
		|  | @ -5,6 +5,7 @@ import androidx.preference.PreferenceManager | |||
| import com.fasterxml.jackson.databind.DeserializationFeature | ||||
| import com.fasterxml.jackson.databind.json.JsonMapper | ||||
| import com.fasterxml.jackson.module.kotlin.KotlinModule | ||||
| import com.lagradost.cloudstream3.animeproviders.DubbedAnimeProvider | ||||
| import com.lagradost.cloudstream3.animeproviders.ShiroProvider | ||||
| import com.lagradost.cloudstream3.movieproviders.MeloMovieProvider | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
|  | @ -27,6 +28,7 @@ object APIHolder { | |||
|     val apis = arrayListOf( | ||||
|         ShiroProvider(), | ||||
|         MeloMovieProvider(), | ||||
|         DubbedAnimeProvider(), | ||||
|     ) | ||||
| 
 | ||||
|     fun getApiFromName(apiName: String?): MainAPI { | ||||
|  | @ -70,12 +72,20 @@ abstract class MainAPI { | |||
| } | ||||
| 
 | ||||
| fun MainAPI.fixUrl(url: String): String { | ||||
|     if (url.startsWith('/')) { | ||||
|         return mainUrl + url | ||||
|     } else if (!url.startsWith("http") && !url.startsWith("//")) { | ||||
|     if(url.startsWith("http")) { | ||||
|         return url | ||||
|     } | ||||
| 
 | ||||
|     val startsWithNoHttp = url.startsWith("//") | ||||
|     if(startsWithNoHttp) { | ||||
|         return "https:$url" | ||||
|     } | ||||
|     else { | ||||
|         if(url.startsWith('/')) { | ||||
|             return mainUrl + url | ||||
|         } | ||||
|         return "$mainUrl/$url" | ||||
|     } | ||||
|     return url | ||||
| } | ||||
| 
 | ||||
| fun sortUrls(urls: List<ExtractorLink>): List<ExtractorLink> { | ||||
|  | @ -168,6 +178,8 @@ fun LoadResponse?.isAnimeBased(): Boolean { | |||
|     return (this.type == TvType.Anime || this.type == TvType.ONA) // && (this is AnimeLoadResponse) | ||||
| } | ||||
| 
 | ||||
| data class AnimeEpisode(val url: String, val name : String? = null) | ||||
| 
 | ||||
| data class AnimeLoadResponse( | ||||
|     val engName: String?, | ||||
|     val japName: String?, | ||||
|  | @ -179,16 +191,16 @@ data class AnimeLoadResponse( | |||
|     override val posterUrl: String?, | ||||
|     override val year: Int?, | ||||
| 
 | ||||
|     val dubEpisodes: ArrayList<String>?, | ||||
|     val subEpisodes: ArrayList<String>?, | ||||
|     val dubEpisodes: ArrayList<AnimeEpisode>?, | ||||
|     val subEpisodes: ArrayList<AnimeEpisode>?, | ||||
|     val showStatus: ShowStatus?, | ||||
| 
 | ||||
|     override val plot: String?, | ||||
|     val tags: ArrayList<String>?, | ||||
|     val synonyms: ArrayList<String>?, | ||||
|     val tags: ArrayList<String>? = null, | ||||
|     val synonyms: ArrayList<String>? = null, | ||||
| 
 | ||||
|     val malId: Int?, | ||||
|     val anilistId: Int?, | ||||
|     val malId: Int? = null, | ||||
|     val anilistId: Int? = null, | ||||
| ) : LoadResponse | ||||
| 
 | ||||
| data class MovieLoadResponse( | ||||
|  | @ -196,7 +208,7 @@ data class MovieLoadResponse( | |||
|     override val url: String, | ||||
|     override val apiName: String, | ||||
|     override val type: TvType, | ||||
|     val movieUrl: String, | ||||
|     val dataUrl: String, | ||||
| 
 | ||||
|     override val posterUrl: String?, | ||||
|     override val year: Int?, | ||||
|  |  | |||
|  | @ -1,8 +1,15 @@ | |||
| package com.lagradost.cloudstream3.animeproviders | ||||
| 
 | ||||
| import com.fasterxml.jackson.annotation.JsonProperty | ||||
| import com.fasterxml.jackson.module.kotlin.readValue | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.APIHolder.unixTime | ||||
| import com.lagradost.cloudstream3.MainAPI | ||||
| import com.lagradost.cloudstream3.mapper | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.getQualityFromName | ||||
| import org.jsoup.Jsoup | ||||
| import java.util.* | ||||
| import kotlin.collections.ArrayList | ||||
| 
 | ||||
| 
 | ||||
| class DubbedAnimeProvider : MainAPI() { | ||||
|     override val mainUrl: String | ||||
|  | @ -12,19 +19,187 @@ class DubbedAnimeProvider : MainAPI() { | |||
|     override val hasQuickSearch: Boolean | ||||
|         get() = true | ||||
| 
 | ||||
|     override fun quickSearch(query: String): ArrayList<Any>? { | ||||
|         val url = "$mainUrl/xz/searchgrid.php?p=1&limit=12&s=$query&_=${unixTime}" | ||||
|         val response = khttp.get(url) | ||||
|     data class QueryEpisodeResultRoot( | ||||
|         @JsonProperty("result") | ||||
|         val result: QueryEpisodeResult, | ||||
|     ) | ||||
| 
 | ||||
|         return super.quickSearch(query) | ||||
|     data class QueryEpisodeResult( | ||||
|         @JsonProperty("anime") val anime: List<EpisodeInfo>, | ||||
|         @JsonProperty("error") val error: Boolean, | ||||
|         @JsonProperty("errorMSG") val errorMSG: String?, | ||||
|     ) | ||||
| 
 | ||||
|     data class EpisodeInfo( | ||||
|         @JsonProperty("serversHTML") val serversHTML: String, | ||||
|         @JsonProperty("title") val title: String, | ||||
|         @JsonProperty("preview_img") val previewImg: String?, | ||||
|         @JsonProperty("wideImg") val wideImg: String?, | ||||
|         @JsonProperty("year") val year: String?, | ||||
|         @JsonProperty("desc") val desc: String?, | ||||
| 
 | ||||
|         /* | ||||
|         @JsonProperty("rowid") val rowid: String, | ||||
|         @JsonProperty("status") val status: String, | ||||
|         @JsonProperty("skips") val skips: String, | ||||
|         @JsonProperty("totalEp") val totalEp: Long, | ||||
|         @JsonProperty("ep") val ep: String, | ||||
|         @JsonProperty("NextEp") val nextEp: Long, | ||||
|         @JsonProperty("slug") val slug: String, | ||||
|         @JsonProperty("showid") val showid: String, | ||||
|         @JsonProperty("Epviews") val epviews: String, | ||||
|         @JsonProperty("TotalViews") val totalViews: String, | ||||
|         @JsonProperty("tags") val tags: String,*/ | ||||
|     ) | ||||
| 
 | ||||
|     private fun getAnimeEpisode(slug: String, isMovie: Boolean): EpisodeInfo { | ||||
|         val url = | ||||
|             mainUrl + (if (isMovie) "/movies/jsonMovie" else "/xz/v3/jsonEpi") + ".php?slug=$slug&_=$unixTime" | ||||
|         val response = khttp.get(url) | ||||
|         val mapped = response.let { mapper.readValue<QueryEpisodeResultRoot>(it.text) } | ||||
| 
 | ||||
|         return mapped.result.anime.first() | ||||
|     } | ||||
| 
 | ||||
|     /* | ||||
|     override fun search(query: String): ArrayList<Any>? { | ||||
| 
 | ||||
|     private fun getIsMovie(href: String): Boolean { | ||||
|         return href.contains("movies/") | ||||
|     } | ||||
| 
 | ||||
|     private fun getSlug(href: String): String { | ||||
|         return href.replace("$mainUrl/", "") | ||||
|     } | ||||
| 
 | ||||
|     override fun quickSearch(query: String): ArrayList<Any> { | ||||
|         val url = "$mainUrl/xz/searchgrid.php?p=1&limit=12&s=$query&_=${unixTime}" | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val items = document.select("div.grid__item > a") | ||||
|         if (items.isEmpty()) return ArrayList() | ||||
|         val returnValue = ArrayList<Any>() | ||||
|         for (i in items) { | ||||
|             val href = fixUrl(i.attr("href")) | ||||
|             val title = i.selectFirst("div.gridtitlek").text() | ||||
|             val img = fixUrl(i.selectFirst("img.grid__img").attr("src")) | ||||
|             returnValue.add( | ||||
|                 if (getIsMovie(href)) { | ||||
|                     MovieSearchResponse( | ||||
|                         title, href, getSlug(href), this.name, TvType.Movie, img, null | ||||
|                     ) | ||||
|                 } else { | ||||
|                     AnimeSearchResponse(title, | ||||
|                         href, | ||||
|                         getSlug(href), | ||||
|                         this.name, | ||||
|                         TvType.Anime, | ||||
|                         img, | ||||
|                         null, | ||||
|                         null, | ||||
|                         EnumSet.of(DubStatus.Dubbed), | ||||
|                         null, | ||||
|                         null) | ||||
|                 }) | ||||
|         } | ||||
|         return returnValue | ||||
|     } | ||||
| 
 | ||||
|     override fun search(query: String): ArrayList<Any> { | ||||
|         val url = "$mainUrl/search/$query" | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val items = document.select("div.resultinner > a.resulta") | ||||
|         if (items.isEmpty()) return ArrayList() | ||||
|         val returnValue = ArrayList<Any>() | ||||
|         for (i in items) { | ||||
|             val innerDiv = i.selectFirst("> div.result") | ||||
|             val href = fixUrl(i.attr("href")) | ||||
|             val img = fixUrl(innerDiv.selectFirst("> div.imgkz > img").attr("src")) | ||||
|             val title = innerDiv.selectFirst("> div.titleresults").text() | ||||
| 
 | ||||
|         mapper.readValue<>() | ||||
|             returnValue.add( | ||||
|                 if (getIsMovie(href)) { | ||||
|                     MovieSearchResponse( | ||||
|                         title, href, getSlug(href), this.name, TvType.Movie, img, null | ||||
|                     ) | ||||
|                 } else { | ||||
|                     AnimeSearchResponse(title, | ||||
|                         href, | ||||
|                         getSlug(href), | ||||
|                         this.name, | ||||
|                         TvType.Anime, | ||||
|                         img, | ||||
|                         null, | ||||
|                         null, | ||||
|                         EnumSet.of(DubStatus.Dubbed), | ||||
|                         null, | ||||
|                         null) | ||||
|                 }) | ||||
|         } | ||||
| 
 | ||||
|         return super.search(query) | ||||
|     }*/ | ||||
|         return returnValue | ||||
|     } | ||||
| 
 | ||||
|     override fun loadLinks(data: String, isCasting: Boolean, callback: (ExtractorLink) -> Unit): Boolean { | ||||
|         val serversHTML = (if (data.startsWith(mainUrl)) { // CLASSIC EPISODE | ||||
|             val slug = getSlug(data) | ||||
|             getAnimeEpisode(slug, false).serversHTML | ||||
|         } else data).replace("\\", "") | ||||
| 
 | ||||
|         val hls = ArrayList("hl=\"(.*?)\"".toRegex().findAll(serversHTML).map { | ||||
|             it.groupValues[1] | ||||
|         }.toList()) | ||||
|         for (hl in hls) { | ||||
|             try { | ||||
|                 val sources = khttp.get("$mainUrl/xz/api/playeri.php?url=$hl&_=$unixTime") | ||||
|                 val txt = sources.text | ||||
|                 val find = "src=\"(.*?)\".*?label=\"(.*?)\"".toRegex().find(txt) | ||||
|                 if (find != null) { | ||||
|                     val quality = find.groupValues[2] | ||||
|                     callback.invoke(ExtractorLink(this.name, | ||||
|                         this.name + " " + quality + if (quality.endsWith('p')) "" else 'p', | ||||
|                         fixUrl(find.groupValues[1]), | ||||
|                         this.mainUrl, | ||||
|                         getQualityFromName(quality))) | ||||
|                 } | ||||
|             } catch (e: Exception) { | ||||
| 
 | ||||
|             } | ||||
|         } | ||||
|         return true | ||||
|     } | ||||
| 
 | ||||
|     override fun load(slug: String): Any { | ||||
|         if (getIsMovie(slug)) { | ||||
|             val realSlug = slug.replace("movies/", "") | ||||
|             val episode = getAnimeEpisode(realSlug, true) | ||||
|             val poster = episode.previewImg ?: episode.wideImg | ||||
|             return MovieLoadResponse(episode.title, | ||||
|                 realSlug, | ||||
|                 this.name, | ||||
|                 TvType.Movie, | ||||
|                 episode.serversHTML, | ||||
|                 if (poster == null) null else fixUrl(poster), | ||||
|                 episode.year?.toIntOrNull(), | ||||
|                 episode.desc, | ||||
|                 null) | ||||
|         } else { | ||||
|             val response = khttp.get("$mainUrl/$slug") | ||||
|             val document = Jsoup.parse(response.text) | ||||
|             val title = document.selectFirst("h4").text() | ||||
|             val descriptHeader = document.selectFirst("div.animeDescript") | ||||
|             val descript = descriptHeader.selectFirst("> p").text() | ||||
|             val year = descriptHeader.selectFirst("> div.distatsx > div.sroverd").text().replace("Released: ", "") | ||||
|                 .toIntOrNull() | ||||
| 
 | ||||
|             val episodes = document.select("a.epibloks").map { | ||||
|                 val epTitle = it.selectFirst("> div.inwel > span.isgrxx")?.text() | ||||
|                 AnimeEpisode(fixUrl(it.attr("href")), epTitle) | ||||
|             } | ||||
| 
 | ||||
|             val img = fixUrl(document.select("div.fkimgs > img").attr("src")) | ||||
|             return AnimeLoadResponse( | ||||
|                 null, null, title, slug, this.name, TvType.Anime, img, year, ArrayList(episodes), null, null, descript, | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -209,7 +209,8 @@ class ShiroProvider : MainAPI() { | |||
|         val mapped = response.let { mapper.readValue<AnimePage>(it.text) } | ||||
|         val data = mapped.data | ||||
|         val isDubbed = data.language == "dubbed" | ||||
|         val episodes = ArrayList<String>(data.episodes?.map { it.videos[0].video_id } ?: ArrayList<String>()) | ||||
|         val episodes = ArrayList<AnimeEpisode>(data.episodes?.map { AnimeEpisode(it.videos[0].video_id) } | ||||
|             ?: ArrayList<AnimeEpisode>()) | ||||
|         val status = when (data.status) { | ||||
|             "current" -> ShowStatus.Ongoing | ||||
|             "finished" -> ShowStatus.Completed | ||||
|  |  | |||
|  | @ -3,9 +3,10 @@ package com.lagradost.cloudstream3.ui | |||
| import android.os.Bundle | ||||
| import android.view.Menu | ||||
| import android.view.View.* | ||||
| import android.widget.* | ||||
| import androidx.appcompat.app.AlertDialog | ||||
| import androidx.core.content.ContentProviderCompat.requireContext | ||||
| import android.widget.AbsListView | ||||
| import android.widget.ArrayAdapter | ||||
| import android.widget.ImageView | ||||
| import android.widget.ListView | ||||
| import com.fasterxml.jackson.databind.DeserializationFeature | ||||
| import com.fasterxml.jackson.databind.json.JsonMapper | ||||
| import com.fasterxml.jackson.module.kotlin.KotlinModule | ||||
|  | @ -15,13 +16,10 @@ import com.google.android.gms.cast.framework.CastButtonFactory | |||
| import com.google.android.gms.cast.framework.CastSession | ||||
| import com.google.android.gms.cast.framework.media.RemoteMediaClient | ||||
| import com.google.android.gms.cast.framework.media.uicontroller.UIController | ||||
| import com.google.android.gms.cast.framework.media.widget.CastSeekBar | ||||
| import com.google.android.gms.cast.framework.media.widget.ExpandedControllerActivity | ||||
| import com.google.android.material.bottomsheet.BottomSheetDialog | ||||
| import com.lagradost.cloudstream3.APIHolder.getApiFromName | ||||
| import com.lagradost.cloudstream3.R | ||||
| import com.lagradost.cloudstream3.UIHelper | ||||
| import com.lagradost.cloudstream3.UIHelper.colorFromAttribute | ||||
| import com.lagradost.cloudstream3.mvvm.Resource | ||||
| import com.lagradost.cloudstream3.mvvm.safeApiCall | ||||
| import com.lagradost.cloudstream3.sortUrls | ||||
|  |  | |||
|  | @ -1129,7 +1129,7 @@ class PlayerFragment : Fragment() { | |||
| 
 | ||||
|         changeSkip() | ||||
| 
 | ||||
|         initPlayer() | ||||
|        // initPlayer() | ||||
|     } | ||||
| 
 | ||||
|     private fun getCurrentUrl(): ExtractorLink? { | ||||
|  |  | |||
|  | @ -86,11 +86,11 @@ class ResultViewModel : ViewModel() { | |||
|                                 val episodes = ArrayList<ResultEpisode>() | ||||
|                                 for ((index, i) in dataList.withIndex()) { | ||||
|                                     episodes.add(context.buildResultEpisode( | ||||
|                                         null, // TODO ADD NAMES | ||||
|                                         i.name, | ||||
|                                         null, | ||||
|                                         index + 1, //TODO MAKE ABLE TO NOT HAVE SOME EPISODE | ||||
|                                         null, // TODO FIX SEASON | ||||
|                                         i, | ||||
|                                         i.url, | ||||
|                                         apiName, | ||||
|                                         (mainId + index + 1), | ||||
|                                         index, | ||||
|  | @ -122,7 +122,7 @@ class ResultViewModel : ViewModel() { | |||
|                                 null, | ||||
|                                 null, | ||||
|                                 0, null, | ||||
|                                 d.movieUrl, | ||||
|                                 d.dataUrl, | ||||
|                                 d.apiName, | ||||
|                                 (mainId + 1), | ||||
|                                 0, | ||||
|  |  | |||
|  | @ -148,7 +148,7 @@ class SearchFragment : Fragment() { | |||
|         allApi.providersActive = requireActivity().getApiSettings() | ||||
| 
 | ||||
|         //searchViewModel.search("iron man") | ||||
|         (activity as AppCompatActivity).loadResult("https://shiro.is/overlord-dubbed", "overlord-dubbed", "Shiro") | ||||
|         //(activity as AppCompatActivity).loadResult("https://shiro.is/overlord-dubbed", "overlord-dubbed", "Shiro") | ||||
| /* | ||||
|         (requireActivity() as AppCompatActivity).supportFragmentManager.beginTransaction() | ||||
|             .setCustomAnimations(R.anim.enter_anim, | ||||
|  |  | |||
|  | @ -28,8 +28,7 @@ class Vidstream { | |||
|             with(khttp.get(url)) { | ||||
|                 val document = Jsoup.parse(this.text) | ||||
|                 val primaryLinks = document.select("ul.list-server-items > li.linkserver") | ||||
|                 val extractedLinksList: MutableList<ExtractorLink> = mutableListOf() | ||||
| 
 | ||||
|                 //val extractedLinksList: MutableList<ExtractorLink> = mutableListOf() | ||||
| 
 | ||||
|                 // All vidstream links passed to extractors | ||||
|                 primaryLinks.forEach { element -> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue