forked from recloudstream/cloudstream
		
	Provider Animekisa (#605)
* Animekisa * Fixed Animekisa servers * Simplified Animekisa, Mcloud Extractror and added Mcloud to Wco
This commit is contained in:
		
							parent
							
								
									e04e6e686e
								
							
						
					
					
						commit
						e8a43b0f85
					
				
					 6 changed files with 207 additions and 1 deletions
				
			
		|  | @ -33,6 +33,7 @@ object APIHolder { | ||||||
|         PeliSmartProvider(), |         PeliSmartProvider(), | ||||||
|         GogoanimeProvider(), |         GogoanimeProvider(), | ||||||
|         AllAnimeProvider(), |         AllAnimeProvider(), | ||||||
|  |         AnimekisaProvider(), | ||||||
|         //ShiroProvider(), // v2 fucked me |         //ShiroProvider(), // v2 fucked me | ||||||
|         //AnimePaheProvider(), //ddos guard |         //AnimePaheProvider(), //ddos guard | ||||||
|         AnimeFlickProvider(), |         AnimeFlickProvider(), | ||||||
|  |  | ||||||
|  | @ -0,0 +1,127 @@ | ||||||
|  | package com.lagradost.cloudstream3.animeproviders | ||||||
|  | 
 | ||||||
|  | import com.fasterxml.jackson.annotation.JsonProperty | ||||||
|  | import com.lagradost.cloudstream3.* | ||||||
|  | import com.lagradost.cloudstream3.utils.AppUtils.parseJson | ||||||
|  | import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
|  | import com.lagradost.cloudstream3.utils.loadExtractor | ||||||
|  | import org.jsoup.Jsoup | ||||||
|  | import java.util.* | ||||||
|  | import kotlin.collections.ArrayList | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class AnimekisaProvider : MainAPI() { | ||||||
|  | 
 | ||||||
|  |     override val mainUrl = "https://animekisa.in" | ||||||
|  |     override val name = "Animekisa" | ||||||
|  |     override val hasMainPage = true | ||||||
|  |     override val hasChromecastSupport = true | ||||||
|  |     override val hasDownloadSupport = true | ||||||
|  |     override val supportedTypes = setOf( | ||||||
|  |         TvType.AnimeMovie, | ||||||
|  |         TvType.OVA, | ||||||
|  |         TvType.Anime, | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     data class Response ( | ||||||
|  |         @JsonProperty("html") val html: String | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     override suspend fun getMainPage(): HomePageResponse { | ||||||
|  |         val urls = listOf( | ||||||
|  |             Pair("$mainUrl/ajax/list/views?type=all", "All animes"), | ||||||
|  |             Pair("$mainUrl/ajax/list/views?type=day", "Trending now"), | ||||||
|  |             Pair("$mainUrl/ajax/list/views?type=week", "Trending by week"), | ||||||
|  |             Pair("$mainUrl/ajax/list/views?type=month", "Trending by month"), | ||||||
|  | 
 | ||||||
|  |             ) | ||||||
|  | 
 | ||||||
|  |         val items = ArrayList<HomePageList>() | ||||||
|  | 
 | ||||||
|  |         for ((url, name) in urls) { | ||||||
|  |             try { | ||||||
|  |                 val home = Jsoup.parse( | ||||||
|  |                     parseJson<Response>( | ||||||
|  |                         app.get( | ||||||
|  |                             url | ||||||
|  |                         ).text | ||||||
|  |                     ).html | ||||||
|  |                 ).select("div.flw-item").map { | ||||||
|  |                     val title = it.selectFirst("h3.title a").text() | ||||||
|  |                     val link = it.selectFirst("a").attr("href") | ||||||
|  |                     val poster = it.selectFirst("img.lazyload").attr("data-src") | ||||||
|  |                     AnimeSearchResponse( | ||||||
|  |                         title, | ||||||
|  |                         link, | ||||||
|  |                         this.name, | ||||||
|  |                         TvType.Anime, | ||||||
|  |                         poster, | ||||||
|  |                         null, | ||||||
|  |                         if (title.contains("(DUB)") || title.contains("(Dub)")) EnumSet.of( | ||||||
|  |                             DubStatus.Dubbed | ||||||
|  |                         ) else EnumSet.of(DubStatus.Subbed), | ||||||
|  |                     ) | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 items.add(HomePageList(name, home)) | ||||||
|  |             } catch (e: Exception) { | ||||||
|  |                 e.printStackTrace() | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (items.size <= 0) throw ErrorLoadingException() | ||||||
|  |         return HomePageResponse(items) | ||||||
|  |     } | ||||||
|  |     override suspend fun search(query: String): List<SearchResponse> { | ||||||
|  |         return app.get("$mainUrl/search/?keyword=$query").document.select("div.flw-item").map { | ||||||
|  |             val title = it.selectFirst("h3 a").text() | ||||||
|  |             val url = it.selectFirst("a.film-poster-ahref").attr("href") | ||||||
|  |                 .replace("watch/","anime/").replace(Regex("(-episode-(\\d+)\\/\$|-episode-(\\d+)\$|-episode-full|-episode-.*-.(\\/|))"),"") | ||||||
|  |             val poster = it.selectFirst(".film-poster img").attr("data-src") | ||||||
|  |             AnimeSearchResponse( | ||||||
|  |                 title, | ||||||
|  |                 url, | ||||||
|  |                 this.name, | ||||||
|  |                 TvType.Anime, | ||||||
|  |                 poster, | ||||||
|  |                 null, | ||||||
|  |                 if (title.contains("(DUB)") || title.contains("(Dub)")) EnumSet.of( | ||||||
|  |                     DubStatus.Dubbed | ||||||
|  |                 ) else EnumSet.of(DubStatus.Subbed), | ||||||
|  |             ) | ||||||
|  |         }.toList() | ||||||
|  |     } | ||||||
|  |     override suspend fun load(url: String): LoadResponse { | ||||||
|  |         val doc = app.get(url, timeout = 120).document | ||||||
|  |         val poster = doc.selectFirst(".mb-2 img").attr("src") ?: doc.selectFirst("head meta[property=og:image]").attr("content") | ||||||
|  |         val title = doc.selectFirst("h1.heading-name a").text() | ||||||
|  |         val description = doc.selectFirst("div.description p").text().trim() | ||||||
|  |         val genres = doc.select("div.row-line a").map { it.text() } | ||||||
|  |         val test = if (doc.selectFirst("div.dp-i-c-right").toString().contains("Airing")) ShowStatus.Ongoing else ShowStatus.Completed | ||||||
|  |         val episodes = doc.select("div.tab-content ul li.nav-item").map { | ||||||
|  |             val link = it.selectFirst("a").attr("href") | ||||||
|  |             AnimeEpisode(link) | ||||||
|  |         } | ||||||
|  |         val type = if (doc.selectFirst(".dp-i-stats").toString().contains("Movies")) TvType.AnimeMovie else TvType.Anime | ||||||
|  |         return newAnimeLoadResponse(title, url, type) { | ||||||
|  |             posterUrl = poster | ||||||
|  |             addEpisodes(DubStatus.Subbed, episodes) | ||||||
|  |             showStatus = test | ||||||
|  |             plot = description | ||||||
|  |             tags = genres | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override suspend fun loadLinks( | ||||||
|  |         data: String, | ||||||
|  |         isCasting: Boolean, | ||||||
|  |         subtitleCallback: (SubtitleFile) -> Unit, | ||||||
|  |         callback: (ExtractorLink) -> Unit | ||||||
|  |     ): Boolean { | ||||||
|  |         app.get(data).document.select("#servers-list ul.nav li a").apmap { | ||||||
|  |             val server = it.attr("data-embed") | ||||||
|  |             loadExtractor(server, data, callback) | ||||||
|  |         } | ||||||
|  |         return true | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| package com.lagradost.cloudstream3.animeproviders | package com.lagradost.cloudstream3.animeproviders | ||||||
| 
 | 
 | ||||||
| import com.lagradost.cloudstream3.* | import com.lagradost.cloudstream3.* | ||||||
|  | import com.lagradost.cloudstream3.extractors.Mcloud | ||||||
| import com.lagradost.cloudstream3.extractors.WcoStream | import com.lagradost.cloudstream3.extractors.WcoStream | ||||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
| import org.json.JSONObject | import org.json.JSONObject | ||||||
|  | @ -242,6 +243,7 @@ class WcoProvider : MainAPI() { | ||||||
| 
 | 
 | ||||||
|         for (server in servers) { |         for (server in servers) { | ||||||
|             WcoStream().getSafeUrl(server["link"].toString(), "")?.forEach(callback) |             WcoStream().getSafeUrl(server["link"].toString(), "")?.forEach(callback) | ||||||
|  |             Mcloud().getSafeUrl(server["link"].toString(), "")?.forEach(callback) | ||||||
|         } |         } | ||||||
|         return true |         return true | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -0,0 +1,75 @@ | ||||||
|  | package com.lagradost.cloudstream3.extractors | ||||||
|  | 
 | ||||||
|  | import com.lagradost.cloudstream3.utils.* | ||||||
|  | import com.lagradost.cloudstream3.app | ||||||
|  | import com.fasterxml.jackson.annotation.JsonProperty | ||||||
|  | import com.lagradost.cloudstream3.USER_AGENT | ||||||
|  | import com.lagradost.cloudstream3.apmap | ||||||
|  | import com.lagradost.cloudstream3.utils.AppUtils.parseJson | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | open class Mcloud : ExtractorApi() { | ||||||
|  |     override val name = "Mcloud" | ||||||
|  |     override val mainUrl = "https://mcloud.to" | ||||||
|  |     override val requiresReferer = true | ||||||
|  |     val headers = mapOf( | ||||||
|  |         "Host" to "mcloud.to", | ||||||
|  |         "User-Agent" to USER_AGENT, | ||||||
|  |         "Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", | ||||||
|  |         "Accept-Language" to "en-US,en;q=0.5", | ||||||
|  |         "DNT" to "1", | ||||||
|  |         "Connection" to "keep-alive", | ||||||
|  |         "Upgrade-Insecure-Requests" to "1", | ||||||
|  |         "Sec-Fetch-Dest" to "iframe", | ||||||
|  |         "Sec-Fetch-Mode" to "navigate", | ||||||
|  |         "Sec-Fetch-Site" to "cross-site", | ||||||
|  |         "Referer" to "https://animekisa.in/", //Referer works for wco and animekisa, probably with others too | ||||||
|  |         "Pragma" to "no-cache", | ||||||
|  |         "Cache-Control" to "no-cache",) | ||||||
|  |     override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink>? { | ||||||
|  |         val link = url.replace("$mainUrl/e/","$mainUrl/info/") | ||||||
|  |         val response = app.get(link, headers = headers).text | ||||||
|  | 
 | ||||||
|  |         data class Sources ( | ||||||
|  |             @JsonProperty("file") val file: String | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         data class Media ( | ||||||
|  |             @JsonProperty("sources") val sources: List<Sources> | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         data class JsonMcloud ( | ||||||
|  |             @JsonProperty("success") val success: Boolean, | ||||||
|  |             @JsonProperty("media") val media: Media, | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         val mapped = response.let { parseJson<JsonMcloud>(it) } | ||||||
|  |         val sources = mutableListOf<ExtractorLink>() | ||||||
|  | 
 | ||||||
|  |         if (mapped.success) | ||||||
|  |             mapped.media.sources.apmap { | ||||||
|  |                 if (it.file.contains("m3u8")) { | ||||||
|  |                     M3u8Helper().m3u8Generation( | ||||||
|  |                         M3u8Helper.M3u8Stream( | ||||||
|  |                             it.file, | ||||||
|  |                             headers = app.get(url).headers.toMap() | ||||||
|  |                         ), true | ||||||
|  |                     ) | ||||||
|  |                         .map { stream -> | ||||||
|  |                             val qualityString = if ((stream.quality ?: 0) == 0) "" else "${stream.quality}p" | ||||||
|  |                             sources.add( | ||||||
|  |                                 ExtractorLink( | ||||||
|  |                                     name, | ||||||
|  |                                     "$name $qualityString", | ||||||
|  |                                     stream.streamUrl, | ||||||
|  |                                     url, | ||||||
|  |                                     getQualityFromName(stream.quality.toString()), | ||||||
|  |                                     true | ||||||
|  |                                 ) | ||||||
|  |                             ) | ||||||
|  |                         } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         return sources | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -7,7 +7,7 @@ import com.lagradost.cloudstream3.mapper | ||||||
| import com.lagradost.cloudstream3.utils.* | import com.lagradost.cloudstream3.utils.* | ||||||
| 
 | 
 | ||||||
| class WcoStream : ExtractorApi() { | class WcoStream : ExtractorApi() { | ||||||
|     override val name = "WcoStream" |     override val name = "VidStream" //Cause works for animekisa and wco | ||||||
|     override val mainUrl = "https://vidstream.pro" |     override val mainUrl = "https://vidstream.pro" | ||||||
|     override val requiresReferer = false |     override val requiresReferer = false | ||||||
|     private val hlsHelper = M3u8Helper() |     private val hlsHelper = M3u8Helper() | ||||||
|  |  | ||||||
|  | @ -95,6 +95,7 @@ val extractorApis: Array<ExtractorApi> = arrayOf( | ||||||
|     Mp4Upload(), |     Mp4Upload(), | ||||||
|     StreamTape(), |     StreamTape(), | ||||||
|     MixDrop(), |     MixDrop(), | ||||||
|  |     Mcloud(), | ||||||
|     XStreamCdn(), |     XStreamCdn(), | ||||||
|     StreamSB(), |     StreamSB(), | ||||||
|     Streamhub(), |     Streamhub(), | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue