From d273da97538ca3bc13cd3b2965e340f6178c49c4 Mon Sep 17 00:00:00 2001 From: darkdemon Date: Fri, 30 Sep 2022 00:34:30 +0530 Subject: [PATCH] add AnimeWorld source --- AnimeWorldProvider/build.gradle.kts | 27 +++ .../src/main/AndroidManifest.xml | 2 + .../kotlin/com/darkdemon/AnimeWorldPlugin.kt | 14 ++ .../com/darkdemon/AnimeWorldProvider.kt | 172 ++++++++++++++++++ 4 files changed, 215 insertions(+) create mode 100644 AnimeWorldProvider/build.gradle.kts create mode 100644 AnimeWorldProvider/src/main/AndroidManifest.xml create mode 100644 AnimeWorldProvider/src/main/kotlin/com/darkdemon/AnimeWorldPlugin.kt create mode 100644 AnimeWorldProvider/src/main/kotlin/com/darkdemon/AnimeWorldProvider.kt diff --git a/AnimeWorldProvider/build.gradle.kts b/AnimeWorldProvider/build.gradle.kts new file mode 100644 index 0000000..b556fdd --- /dev/null +++ b/AnimeWorldProvider/build.gradle.kts @@ -0,0 +1,27 @@ +version = 1 + + +cloudstream { + language = "hi" + // All of these properties are optional, you can safely remove them + + description = "If the videos are not loading, click on webviewicon(earth icon) on details and play the episode.Skip the ads and now play using app" + authors = listOf("darkdemon") + + /** + * Status int as the following: + * 0: Down + * 1: Ok + * 2: Slow + * 3: Beta only + * */ + status = 1 // will be 3 if unspecified + tvTypes = listOf( + "TvSeries", + "Movie", + "Anime", + "Cartoon" + ) + + iconUrl = "https://www.google.com/s2/favicons?domain=anime-world.in&sz=%size%" +} diff --git a/AnimeWorldProvider/src/main/AndroidManifest.xml b/AnimeWorldProvider/src/main/AndroidManifest.xml new file mode 100644 index 0000000..7fbfe5f --- /dev/null +++ b/AnimeWorldProvider/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + diff --git a/AnimeWorldProvider/src/main/kotlin/com/darkdemon/AnimeWorldPlugin.kt b/AnimeWorldProvider/src/main/kotlin/com/darkdemon/AnimeWorldPlugin.kt new file mode 100644 index 0000000..f6fe5e8 --- /dev/null +++ b/AnimeWorldProvider/src/main/kotlin/com/darkdemon/AnimeWorldPlugin.kt @@ -0,0 +1,14 @@ +package com.darkdemon + +import com.lagradost.cloudstream3.plugins.CloudstreamPlugin +import com.lagradost.cloudstream3.plugins.Plugin +import android.content.Context + +@CloudstreamPlugin +class AnimeWorldPlugin: Plugin() { + override fun load(context: Context) { + // All providers should be added in this manner. Please don't edit the providers list directly. + registerMainAPI(AnimeWorldProvider()) + registerExtractorAPI(Vanfem()) + } +} diff --git a/AnimeWorldProvider/src/main/kotlin/com/darkdemon/AnimeWorldProvider.kt b/AnimeWorldProvider/src/main/kotlin/com/darkdemon/AnimeWorldProvider.kt new file mode 100644 index 0000000..4fef83c --- /dev/null +++ b/AnimeWorldProvider/src/main/kotlin/com/darkdemon/AnimeWorldProvider.kt @@ -0,0 +1,172 @@ + +package com.darkdemon + +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer +import com.lagradost.cloudstream3.extractors.XStreamCdn +import com.lagradost.cloudstream3.utils.* +import org.jsoup.nodes.Element + +class AnimeWorldProvider : MainAPI() { // all providers must be an instance of MainAPI + override var mainUrl = "https://anime-world.in" + override var name = "Anime World" + override val hasMainPage = true + override var lang = "hi" + override val hasDownloadSupport = true + override val supportedTypes = setOf( + TvType.Movie, + TvType.TvSeries, + TvType.Anime, + TvType.Cartoon + ) + + override val mainPage = mainPageOf( + "$mainUrl/series/page/" to "Series", + "$mainUrl/movies/page/" to "Movies", + "$mainUrl/category/cartoon/page/" to "Cartoon", + "$mainUrl/category/anime/page/" to "Anime", + "$mainUrl/category/cartoon-network/page/" to "Cartoon Network", + "$mainUrl/category/disney/page/" to "Disney", + "$mainUrl/category/marvel-hq/page/" to "Marvel", + "$mainUrl/category/hungama-tv/page/" to "Hungama TV", + "$mainUrl/category/nickelodeon/page/" to "Nickelodeon", + "$mainUrl/category/sonic/page/" to "Sonic", + "$mainUrl/category/amazon-prime/page/" to "Amazon Prime", + "$mainUrl/category/netflix/page/" to "Netflix", + ) + + override suspend fun getMainPage( + page: Int, + request: MainPageRequest + ): HomePageResponse { + val document = app.get(request.data + page).document + val home = document.select("article").mapNotNull { + it.toSearchResult() + } + return newHomePageResponse(request.name, home) + } + + private fun Element.toSearchResult(): SearchResponse? { + val title = this.selectFirst(".entry-title")?.text()?.trim() ?: return null + val href = fixUrl(this.selectFirst("a")?.attr("href").toString()) + val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src")) + val year = this.select(".year").text().trim().toIntOrNull() + + return newMovieSearchResponse(title, href, TvType.Movie) { + this.posterUrl = posterUrl + this.year = year + } + } + + override suspend fun search(query: String): List { + val document = app.get("$mainUrl/?s=$query").document + + return document.select("article").mapNotNull { + it.toSearchResult() + } + } + + override suspend fun load(url: String): LoadResponse? { + val document = app.get(url).document + + val title = document.selectFirst(".entry-title")?.text()?.trim() ?: return null + val poster = fixUrlNull(document.selectFirst(".post-thumbnail img")?.attr("src")) + val tags = document.select(".genres a").map { it.text() } + val year = document.select(".year").text().trim().toIntOrNull() + val tvType = if (document.select(".episodes button > span").isNullOrEmpty() + ) TvType.Movie else TvType.TvSeries + val description = document.selectFirst(".description > p:nth-child(1)")?.text()?.trim() + val trailer = fixUrlNull(document.select("iframe").attr("src")) + val rating = document.select("span.num").text().toRatingInt() + //val actors = document.select("#cast > div:nth-child(4)").map { it.text() } + val recommendations = document.select("article").mapNotNull { + it.toSearchResult() + } + + return if (tvType == TvType.TvSeries) { + val episodes : MutableList = mutableListOf() + document.select(".choose-season ul.sub-menu a").mapNotNull { element -> + val html = app.post( + url = "$mainUrl/wp-admin/admin-ajax.php", + data = mapOf( + "action" to "action_select_season", + "season" to element.attr("data-season"), + "post" to element.attr("data-post") + ), + referer = url, + headers = mapOf("X-Requested-With" to "XMLHttpRequest") + ).document + + episodes += html.select("article").mapNotNull { + val href = fixUrl(it.select("a").attr("href")?: return null) + val name = it.select("h2").text().trim() + val thumbs = it.select("img").attr("src") + val season = element.attr("data-season").toInt() + val episode = it.select(".num-epi").text().split("x").last().toInt() + Episode( + href, + name, + season, + episode, + thumbs + ) + } + } + + newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) { + this.posterUrl = poster + this.year = year + this.plot = description + this.tags = tags + this.rating = rating + this.recommendations = recommendations + addTrailer(trailer) + } + } else { + newMovieLoadResponse(title, url, TvType.Movie, url) { + this.posterUrl = poster + this.year = year + this.plot = description + this.tags = tags + this.rating = rating + this.recommendations = recommendations + addTrailer(trailer) + } + } + } + + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + + val document = app.get(data).document + val langPair = document.select(".aa-tbs li").map{it.select("a").attr("href").replace("#","") to it.select(".server").text().split("-").last().trim()}.toMap() + document.select(".aa-cn div").map { res -> + loadExtractor( + res.select("iframe").attr("data-src"), + referer = data, + subtitleCallback, + ){ link -> + callback.invoke(ExtractorLink( + link.source, + link.name + " " + langPair[res.attr("id")], + link.url, + link.referer, + Qualities.Unknown.value, + link.isM3u8, + link.headers, + link.extractorData + )) + } + } + return true + } +} +class Vanfem: XStreamCdn() { + override val name: String = "Vanfem" + override val mainUrl: String = "https://vanfem.com" + override var domainUrl: String = "vanfem.com" +} \ No newline at end of file