diff --git a/Animixplay/src/main/kotlin/com/hexated/Animixplay.kt b/Animixplay/src/main/kotlin/com/hexated/Animixplay.kt index e6aa99eb..1a8b8707 100644 --- a/Animixplay/src/main/kotlin/com/hexated/Animixplay.kt +++ b/Animixplay/src/main/kotlin/com/hexated/Animixplay.kt @@ -51,7 +51,7 @@ class Animixplay : MainAPI() { "$mainUrl/api/search" to "Movie", ) - private var newPagination : String? = null + private var newPagination: String? = null override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse { val items = mutableListOf() val paged = page.toString() @@ -132,35 +132,21 @@ class Animixplay : MainAPI() { } - override suspend fun search(query: String):List?{ - val searchData = app.post( + override suspend fun search(query: String): List? { + return app.post( url = "https://v1.ij7p9towl8uj4qafsopjtrjk.workers.dev", referer = mainUrl, data = mapOf( "q2" to query, "origin" to "1", "root" to "animixplay.to", - "d" to "gogoanime.tel") - ) - return Jsoup.parse(JSONObject(searchData.text).get("result").toString()).select("div").map{elem-> + "d" to "gogoanime.tel" + ) + ).parsedSafe()?.result?.let { + Jsoup.parse(it).select("div").map { elem -> - val href = fixUrl(elem.select("a").attr("href")) - val title = elem.select("a").attr("title") - newAnimeSearchResponse(title, href, TvType.Anime) { - this.posterUrl = elem.select("img").attr("src") - addDubStatus(isDub = title.contains("Dub")) - } - } - } - - override suspend fun quickSearch(query: String): List? { - return app.post( - "https://cdn.animixplay.to/api/search", - data = mapOf("qfast" to query, "root" to URI(mainUrl).host) - ).parsedSafe()?.result?.let { - Jsoup.parse(it).select("a").map { elem -> - val href = elem.attr("href") - val title = elem.select("p.name").text() + val href = fixUrl(elem.select("a").attr("href")) + val title = elem.select("a").attr("title") newAnimeSearchResponse(title, href, TvType.Anime) { this.posterUrl = elem.select("img").attr("src") addDubStatus(isDub = title.contains("Dub")) @@ -169,189 +155,206 @@ class Animixplay : MainAPI() { } } - - override suspend fun load(url: String): LoadResponse? { - - val (fixUrl, malId) = if (url.contains("/anime/")) { - listOf(url, Regex("anime/([0-9]+)/?").find(url)?.groupValues?.get(1)) - } else { - val malId = app.get(url).text.substringAfterLast("malid = '").substringBefore("';") - listOf("$mainUrl/anime/$malId", malId) + override suspend fun quickSearch(query: String): List? { + return app.post( + "https://cdn.animixplay.to/api/search", + data = mapOf("qfast" to query, "root" to URI(mainUrl).host) + ).parsedSafe()?.result?.let { + Jsoup.parse(it).select("a").map { elem -> + val href = elem.attr("href") + val title = elem.select("p.name").text() + newAnimeSearchResponse(title, href, TvType.Anime) { + this.posterUrl = elem.select("img").attr("src") + addDubStatus(isDub = title.contains("Dub")) + } + } + } } - val anilistId = app.post( - "https://graphql.anilist.co/", data = mapOf( - "query" to "{Media(idMal:$malId,type:ANIME){id}}", - ) - ).parsedSafe()?.data?.media?.id - val res = app.get("$mainUrl/assets/mal/$malId.json").parsedSafe() - ?: throw ErrorLoadingException("Invalid json responses") + override suspend fun load(url: String): LoadResponse? { - val subEpisodes = mutableListOf() - val dubEpisodes = mutableListOf() + val (fixUrl, malId) = if (url.contains("/anime/")) { + listOf(url, Regex("anime/([0-9]+)/?").find(url)?.groupValues?.get(1)) + } else { + val malId = app.get(url).text.substringAfterLast("malid = '").substringBefore("';") + listOf("$mainUrl/anime/$malId", malId) + } - app.post("$mainUrl/api/search", data = mapOf("recomended" to "$malId")) - .parsedSafe()?.data?.filter { it.type == "GOGO" }?.map { item -> - item.items?.apmap { server -> - val dataEps = - app.get(fixUrl(server.url.toString())).document.select("div#epslistplace") - .text().trim() - Regex("\"([0-9]+)\":\"(\\S+?)\"").findAll(dataEps).toList() - .map { it.groupValues[1] to it.groupValues[2] }.map { (ep, link) -> - val episode = Episode(fixUrl(link), episode = ep.toInt() + 1) - if (server.url?.contains("-dub") == true) { - dubEpisodes.add(episode) - } else { - subEpisodes.add(episode) + val anilistId = app.post( + "https://graphql.anilist.co/", data = mapOf( + "query" to "{Media(idMal:$malId,type:ANIME){id}}", + ) + ).parsedSafe()?.data?.media?.id + + val res = app.get("$mainUrl/assets/mal/$malId.json").parsedSafe() + ?: throw ErrorLoadingException("Invalid json responses") + + val subEpisodes = mutableListOf() + val dubEpisodes = mutableListOf() + + app.post("$mainUrl/api/search", data = mapOf("recomended" to "$malId")) + .parsedSafe()?.data?.filter { it.type == "GOGO" }?.map { item -> + item.items?.apmap { server -> + val dataEps = + app.get(fixUrl(server.url.toString())).document.select("div#epslistplace") + .text().trim() + Regex("\"([0-9]+)\":\"(\\S+?)\"").findAll(dataEps).toList() + .map { it.groupValues[1] to it.groupValues[2] }.map { (ep, link) -> + val episode = Episode(fixUrl(link), episode = ep.toInt() + 1) + if (server.url?.contains("-dub") == true) { + dubEpisodes.add(episode) + } else { + subEpisodes.add(episode) + } } - } + } } + + val recommendations = app.get("$mainUrl/assets/similar/$malId.json") + .parsedSafe()?.recommendations?.mapNotNull { rec -> + newAnimeSearchResponse( + rec.title ?: return@mapNotNull null, + "$mainUrl/anime/${rec.malId}/", + TvType.Anime + ) { + this.posterUrl = rec.imageUrl + addDubStatus(dubExist = false, subExist = true) + } + } + + return newAnimeLoadResponse( + res.title ?: return null, + url, + TvType.Anime + ) { + engName = res.title + posterUrl = res.imageUrl + this.year = res.aired?.from?.split("-")?.firstOrNull()?.toIntOrNull() + showStatus = getStatus(res.status) + plot = res.synopsis + this.tags = res.genres?.mapNotNull { it.name } + this.recommendations = recommendations + addMalId(malId?.toIntOrNull()) + addAniListId(anilistId?.toIntOrNull()) + addTrailer(res.trailerUrl) + if (subEpisodes.isNotEmpty()) addEpisodes(DubStatus.Subbed, subEpisodes) + if (dubEpisodes.isNotEmpty()) addEpisodes(DubStatus.Dubbed, dubEpisodes) } - val recommendations = app.get("$mainUrl/assets/similar/$malId.json") - .parsedSafe()?.recommendations?.mapNotNull { rec -> - newAnimeSearchResponse( - rec.title ?: return@mapNotNull null, - "$mainUrl/anime/${rec.malId}/", - TvType.Anime - ) { - this.posterUrl = rec.imageUrl - addDubStatus(dubExist = false, subExist = true) - } - } - - return newAnimeLoadResponse( - res.title ?: return null, - url, - TvType.Anime - ) { - engName = res.title - posterUrl = res.imageUrl - this.year = res.aired?.from?.split("-")?.firstOrNull()?.toIntOrNull() - showStatus = getStatus(res.status) - plot = res.synopsis - this.tags = res.genres?.mapNotNull { it.name } - this.recommendations = recommendations - addMalId(malId?.toIntOrNull()) - addAniListId(anilistId?.toIntOrNull()) - addTrailer(res.trailerUrl) - if (subEpisodes.isNotEmpty()) addEpisodes(DubStatus.Subbed, subEpisodes) - if (dubEpisodes.isNotEmpty()) addEpisodes(DubStatus.Dubbed, dubEpisodes) } + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + + val iframe = app.get(data) + val iframeDoc = iframe.document + + argamap({ + iframeDoc.select(".list-server-items > .linkserver") + .forEach { element -> + val status = element.attr("data-status") ?: return@forEach + if (status != "1") return@forEach + val extractorData = element.attr("data-video") ?: return@forEach + loadExtractor(extractorData, iframe.url, subtitleCallback, callback) + } + }, { + val iv = "3134003223491201" + val secretKey = "37911490979715163134003223491201" + val secretDecryptKey = "54674138327930866480207815084989" + GogoanimeProvider.extractVidstream( + iframe.url, + this.name, + callback, + iv, + secretKey, + secretDecryptKey, + isUsingAdaptiveKeys = false, + isUsingAdaptiveData = true, + iframeDocument = iframeDoc + ) + }) + return true } - override suspend fun loadLinks( - data: String, - isCasting: Boolean, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ): Boolean { + private data class IdAni( + @JsonProperty("id") val id: String? = null, + ) - val iframe = app.get(data) - val iframeDoc = iframe.document + private data class MediaAni( + @JsonProperty("Media") val media: IdAni? = null, + ) - argamap({ - iframeDoc.select(".list-server-items > .linkserver") - .forEach { element -> - val status = element.attr("data-status") ?: return@forEach - if (status != "1") return@forEach - val extractorData = element.attr("data-video") ?: return@forEach - loadExtractor(extractorData, iframe.url, subtitleCallback, callback) - } - }, { - val iv = "3134003223491201" - val secretKey = "37911490979715163134003223491201" - val secretDecryptKey = "54674138327930866480207815084989" - GogoanimeProvider.extractVidstream( - iframe.url, - this.name, - callback, - iv, - secretKey, - secretDecryptKey, - isUsingAdaptiveKeys = false, - isUsingAdaptiveData = true, - iframeDocument = iframeDoc - ) - }) - return true - } + private data class DataAni( + @JsonProperty("data") val data: MediaAni? = null, + ) + private data class Items( + @JsonProperty("url") val url: String? = null, + @JsonProperty("title") val title: String? = null, + ) + private data class Episodes( + @JsonProperty("type") val type: String? = null, + @JsonProperty("items") val items: ArrayList? = arrayListOf(), + ) + private data class Data( + @JsonProperty("data") val data: ArrayList? = arrayListOf(), + ) - private data class IdAni( - @JsonProperty("id") val id: String? = null, - ) + private data class Aired( + @JsonProperty("from") val from: String? = null, + ) - private data class MediaAni( - @JsonProperty("Media") val media: IdAni? = null, - ) + private data class Genres( + @JsonProperty("name") val name: String? = null, + ) - private data class DataAni( - @JsonProperty("data") val data: MediaAni? = null, - ) + private data class RecResult( + @JsonProperty("recommendations") val recommendations: ArrayList? = arrayListOf(), + ) - private data class Items( - @JsonProperty("url") val url: String? = null, - @JsonProperty("title") val title: String? = null, - ) + private data class Recommendations( + @JsonProperty("mal_id") val malId: String? = null, + @JsonProperty("image_url") val imageUrl: String? = null, + @JsonProperty("title") val title: String? = null, + ) - private data class Episodes( - @JsonProperty("type") val type: String? = null, - @JsonProperty("items") val items: ArrayList? = arrayListOf(), - ) + private data class AnimeDetail( + @JsonProperty("title") val title: String? = null, + @JsonProperty("image_url") val imageUrl: String? = null, + @JsonProperty("type") val type: String? = null, + @JsonProperty("aired") val aired: Aired? = null, + @JsonProperty("status") val status: String? = null, + @JsonProperty("synopsis") val synopsis: String? = null, + @JsonProperty("trailer_url") val trailerUrl: String? = null, + @JsonProperty("genres") val genres: ArrayList? = arrayListOf(), + ) - private data class Data( - @JsonProperty("data") val data: ArrayList? = arrayListOf(), - ) + private data class Search( + @JsonProperty("result") val result: String? = null, + ) - private data class Aired( - @JsonProperty("from") val from: String? = null, - ) + private data class Result( + @JsonProperty("result") val result: ArrayList = arrayListOf(), + @JsonProperty("last") val last: Any? = null, + ) - private data class Genres( - @JsonProperty("name") val name: String? = null, - ) + private data class Anime( + @JsonProperty("title") val title: String? = null, + @JsonProperty("url") val url: String? = null, + @JsonProperty("img") val img: String? = null, + @JsonProperty("picture") val picture: String? = null, + @JsonProperty("infotext") val infotext: String? = null, + ) - private data class RecResult( - @JsonProperty("recommendations") val recommendations: ArrayList? = arrayListOf(), - ) - - private data class Recommendations( - @JsonProperty("mal_id") val malId: String? = null, - @JsonProperty("image_url") val imageUrl: String? = null, - @JsonProperty("title") val title: String? = null, - ) - - private data class AnimeDetail( - @JsonProperty("title") val title: String? = null, - @JsonProperty("image_url") val imageUrl: String? = null, - @JsonProperty("type") val type: String? = null, - @JsonProperty("aired") val aired: Aired? = null, - @JsonProperty("status") val status: String? = null, - @JsonProperty("synopsis") val synopsis: String? = null, - @JsonProperty("trailer_url") val trailerUrl: String? = null, - @JsonProperty("genres") val genres: ArrayList? = arrayListOf(), - ) - - private data class Search( + private data class FullSearch( @JsonProperty("result") val result: String? = null, ) - private data class Result( - @JsonProperty("result") val result: ArrayList = arrayListOf(), - @JsonProperty("last") val last: Any? = null, - ) - - private data class Anime( - @JsonProperty("title") val title: String? = null, - @JsonProperty("url") val url: String? = null, - @JsonProperty("img") val img: String? = null, - @JsonProperty("picture") val picture: String? = null, - @JsonProperty("infotext") val infotext: String? = null, - ) - } \ No newline at end of file