package com.hexated import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.utils.* import org.jsoup.Jsoup import org.jsoup.nodes.Element class Animasu : MainAPI() { override var mainUrl = "https://animasu.cc" override var name = "Animasu" override val hasMainPage = true override var lang = "id" override val hasDownloadSupport = true override val supportedTypes = setOf( TvType.Anime, TvType.AnimeMovie, TvType.OVA ) companion object { fun getType(t: String?): TvType { if(t == null) return TvType.Anime return when { t.contains("Tv", true) -> TvType.Anime t.contains("Movie", true) -> TvType.AnimeMovie t.contains("OVA", true) || t.contains("Special", true) -> TvType.OVA else -> TvType.Anime } } fun getStatus(t: String?): ShowStatus { if(t == null) return ShowStatus.Completed return when { t.contains("Sedang Tayang", true) -> ShowStatus.Ongoing else -> ShowStatus.Completed } } } override val mainPage = mainPageOf( "urutan=update" to "Baru diupdate", "status=&tipe=&urutan=publikasi" to "Baru ditambahkan", "status=&tipe=&urutan=populer" to "Terpopuler", "status=&tipe=&urutan=rating" to "Rating Tertinggi", "status=&tipe=Movie&urutan=update" to "Movie Terbaru", "status=&tipe=Movie&urutan=populer" to "Movie Terpopuler", ) override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse { val document = app.get("$mainUrl/pencarian/?${request.data}&halaman=$page").document val home = document.select("div.listupd div.bs").map { it.toSearchResult() } return newHomePageResponse(request.name, home) } private fun getProperAnimeLink(uri: String): String { return if (uri.contains("/anime/")) { uri } else { var title = uri.substringAfter("$mainUrl/") title = when { (title.contains("-episode")) && !(title.contains("-movie")) -> title.substringBefore( "-episode" ) (title.contains("-movie")) -> title.substringBefore("-movie") else -> title } "$mainUrl/anime/$title" } } private fun Element.toSearchResult(): AnimeSearchResponse { val href = getProperAnimeLink(fixUrlNull(this.selectFirst("a")?.attr("href")).toString()) val title = this.select("div.tt").text().trim() val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src")) val epNum = this.selectFirst("span.epx")?.text()?.filter { it.isDigit() }?.toIntOrNull() return newAnimeSearchResponse(title, href, TvType.Anime) { this.posterUrl = posterUrl addSub(epNum) } } override suspend fun search(query: String): List { return app.get("$mainUrl/?s=$query").document.select("div.listupd div.bs").map { it.toSearchResult() } } override suspend fun load(url: String): LoadResponse { val document = app.get(url).document val title = document.selectFirst("div.infox h1")?.text().toString().replace("Sub Indo", "").trim() val poster = document.selectFirst("div.bigcontent img")?.attr("src")?.replace("\n", "") val table = document.selectFirst("div.infox div.spe") val type = table?.selectFirst("span:contains(Jenis:)")?.ownText() val year = table?.selectFirst("span:contains(Rilis:)")?.ownText()?.substringAfterLast(",")?.trim()?.toIntOrNull() val status = table?.selectFirst("span:contains(Status:) font")?.text() val trailer = document.selectFirst("div.trailer iframe")?.attr("src") val episodes = document.select("ul#daftarepisode > li").map { val link = fixUrl(it.selectFirst("a")!!.attr("href")) val name = it.selectFirst("a")?.text() ?: "" val episode = Regex("Episode\\s?(\\d+)").find(name)?.groupValues?.getOrNull(0)?.toIntOrNull() Episode(link, name, episode = episode) }.reversed() return newAnimeLoadResponse(title, url, getType(type)) { posterUrl = poster this.year = year addEpisodes(DubStatus.Subbed, episodes) showStatus = getStatus(status) plot = document.select("div.sinopsis p").text() this.tags = table?.select("span:contains(Genre:) a")?.map { it.text() } addTrailer(trailer) } } override suspend fun loadLinks( data: String, isCasting: Boolean, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ): Boolean { val document = app.get(data).document document.select(".mobius > .mirror > option").mapNotNull { fixUrl(Jsoup.parse(base64Decode(it.attr("value"))).select("iframe").attr("src")) to it.text() }.apmap { (iframe, quality) -> loadFixedExtractor(iframe, quality, "$mainUrl/", subtitleCallback, callback) } return true } private suspend fun loadFixedExtractor( url: String, quality: String?, referer: String? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ) { loadExtractor(url, referer, subtitleCallback) { link -> callback.invoke( ExtractorLink( link.name, link.name, link.url, link.referer, if(link.type != ExtractorLinkType.M3U8) getIndexQuality(quality) else link.quality, link.type, link.headers, link.extractorData ) ) } } private fun getIndexQuality(str: String?): Int { return Regex("(\\d{3,4})[pP]").find(str ?: "")?.groupValues?.getOrNull(1)?.toIntOrNull() ?: Qualities.Unknown.value } }