diff --git a/AnimeiatProvider/build.gradle.kts b/AnimeiatProvider/build.gradle.kts new file mode 100644 index 0000000..723d77f --- /dev/null +++ b/AnimeiatProvider/build.gradle.kts @@ -0,0 +1,14 @@ +version = 1 + +cloudstream { + description = "" + authors = listOf( "ImZaw" ) + + language = "ar" + + status = 1 + + tvTypes = listOf( "Anime" ) + + iconUrl = "https://www.google.com/s2/favicons?domain=animeiat.tv&sz=%size%" +} \ No newline at end of file diff --git a/AnimeiatProvider/src/main/AndroidManifest.xml b/AnimeiatProvider/src/main/AndroidManifest.xml new file mode 100644 index 0000000..72204b5 --- /dev/null +++ b/AnimeiatProvider/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/AnimeiatProvider/src/main/kotlin/com/animeiat/AnimeiatPlugin.kt b/AnimeiatProvider/src/main/kotlin/com/animeiat/AnimeiatPlugin.kt new file mode 100644 index 0000000..fa3c66f --- /dev/null +++ b/AnimeiatProvider/src/main/kotlin/com/animeiat/AnimeiatPlugin.kt @@ -0,0 +1,11 @@ +package com.animeiat +import com.lagradost.cloudstream3.plugins.CloudstreamPlugin +import com.lagradost.cloudstream3.plugins.Plugin +import android.content.Context + +@CloudstreamPlugin +class AnimeiatPlugin: Plugin() { + override fun load(context: Context) { + registerMainAPI(Animeiat()) + } +} \ No newline at end of file diff --git a/AnimeiatProvider/src/main/kotlin/com/animeiat/AnimeiatProvider.kt b/AnimeiatProvider/src/main/kotlin/com/animeiat/AnimeiatProvider.kt new file mode 100644 index 0000000..035d6c2 --- /dev/null +++ b/AnimeiatProvider/src/main/kotlin/com/animeiat/AnimeiatProvider.kt @@ -0,0 +1,174 @@ +package com.animeiat + + +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.loadExtractor +import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.cloudstream3.utils.AppUtils.parseJson +import com.lagradost.nicehttp.Requests + +class Animeiat : MainAPI() { + override var lang = "ar" + override var mainUrl = "https://api.animeiat.co/v1" + val pageUrl = "https://www.animeiat.tv" + override var name = "Animeiat" + override val usesWebView = false + override val hasMainPage = true + override val supportedTypes = + setOf(TvType.Anime, TvType.AnimeMovie) + + data class Data ( + @JsonProperty("anime_name" ) var animeName : String? = null, + @JsonProperty("title" ) var title : String? = null, + @JsonProperty("slug" ) var slug : String? = null, + @JsonProperty("story" ) var story : String? = null, + @JsonProperty("other_names" ) var otherNames : String? = null, + @JsonProperty("total_episodes" ) var totalEpisodes : Int? = null, + @JsonProperty("number" ) var number : Int? = null, + @JsonProperty("age" ) var age : String? = null, + @JsonProperty("type" ) var type : String? = null, + @JsonProperty("status" ) var status : String? = null, + @JsonProperty("poster_path" ) var posterPath : String? = null, + ) + data class All ( + @JsonProperty("data" ) var data : ArrayList = arrayListOf(), + ) + + override val mainPage = mainPageOf( + "$mainUrl/anime?page=" to "Anime", + "$mainUrl/home/sticky-episodes?page=" to "Episodes (H)" + ) + + override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse { + val json = parseJson(app.get(request.data + page).text) + val list = json.data.map { + newAnimeSearchResponse( + it.animeName ?: it.title.toString(), + mainUrl + "/anime/" + it.slug.toString().replace("-episode.*".toRegex(),""), + if (it.type == "movie") TvType.AnimeMovie else if (it.type == "tv") TvType.Anime else TvType.OVA, + ) { + addDubStatus(false, it.totalEpisodes ?: it.number) + this.otherName = it.otherNames?.split("\n")?.last() + this.posterUrl = "https://api.animeiat.co/storage/" + it.posterPath + } + } + return HomePageResponse(arrayListOf( + HomePageList( + request.name.replace(" (H)",""), list, request.name.contains("(H)") + ) + ) + ) + } + + override suspend fun search(query: String): List { + val json = parseJson(app.get("$mainUrl/anime?q=$query").text) + return json.data.map { + newAnimeSearchResponse( + it.animeName.toString(), + mainUrl + "/anime/" + it.slug.toString(), + if(it.type == "movie") TvType.AnimeMovie else if(it.type == "tv") TvType.Anime else TvType.OVA, + ) { + addDubStatus(false, it.totalEpisodes) + this.otherName = it.otherNames?.split("\n")?.last() + this.posterUrl = "https://api.animeiat.co/storage/" + it.posterPath + } + } + + } + + data class Year ( + @JsonProperty("name" ) var name : String? = null, + + ) + data class Genres ( + @JsonProperty("name" ) var name : String? = null, + ) + data class LoadData ( + @JsonProperty("anime_name" ) var animeName : String? = null, + @JsonProperty("slug" ) var slug : String? = null, + @JsonProperty("story" ) var story : String? = null, + @JsonProperty("other_names" ) var otherNames : String? = null, + @JsonProperty("age" ) var age : String? = null, + @JsonProperty("type" ) var type : String? = null, + @JsonProperty("status" ) var status : String? = null, + @JsonProperty("poster_path" ) var posterPath : String? = null, + @JsonProperty("year" ) var year : Year? = Year(), + @JsonProperty("genres" ) var genres : ArrayList = arrayListOf(), + + ) + data class Load ( + + @JsonProperty("data" ) var data : LoadData? = LoadData() + + ) + data class Meta ( + @JsonProperty("last_page" ) var lastPage : Int? = null, + ) + data class EpisodeData ( + @JsonProperty("title" ) var title : String? = null, + @JsonProperty("slug" ) var slug : String? = null, + @JsonProperty("number" ) var number : Int? = null, + @JsonProperty("video_id" ) var videoId : Int? = null, + @JsonProperty("poster_path" ) var posterPath : String? = null, + ) + data class Episodes ( + @JsonProperty("data" ) var data : ArrayList = arrayListOf(), + @JsonProperty("meta" ) var meta : Meta = Meta() + ) + override suspend fun load(url: String): LoadResponse { + val loadSession = Requests() + val request = loadSession.get(url).text + val json = parseJson(request) + val episodes = arrayListOf() + (1..parseJson(loadSession.get("$url/episodes").text).meta.lastPage!!).map { pageNumber -> + parseJson(loadSession.get("$url/episodes?page=$pageNumber").text).data.map { + episodes.add( + Episode( + "$pageUrl/watch/"+json.data?.slug, + it.title, + null, + it.number, + "https://api.animeiat.co/storage/" + it.posterPath, + + ) + ) + } + } + return newAnimeLoadResponse(json.data?.animeName.toString(), "$pageUrl/watch/"+json.data?.slug, if(json.data?.type == "movie") TvType.AnimeMovie else if(json.data?.type == "tv") TvType.Anime else TvType.OVA) { + japName = json.data?.otherNames?.split("\n")?.get(1) + engName = json.data?.animeName + posterUrl = "https://api.animeiat.co/storage/" + json.data?.posterPath + this.year = json.data?.year?.name?.toIntOrNull() + addEpisodes(DubStatus.Subbed, episodes) + plot = json.data?.story + tags = json.data?.genres?.map { it.name.toString() } + this.showStatus = if(json.data?.status == "completed") ShowStatus.Completed else ShowStatus.Ongoing + } + } + + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + val url = if(data.contains("-episode")) data else "$data-episode-1" + val doc = app.get(url).document + val script = doc.select("body > script").first()?.html() + val id = script?.replace(".*4\",slug:\"|\",duration:.*".toRegex(),"") + val player = app.get("$pageUrl/player/$id").document + player.select("source").map { + callback.invoke( + ExtractorLink( + this.name, + this.name, + it.attr("src"), + pageUrl, + it.attr("size").toInt(), + ) + ) + } + return true + } +} \ No newline at end of file