mirror of
https://github.com/hexated/cloudstream-extensions-hexated.git
synced 2024-08-15 00:03:22 +00:00
Merge pull request #13 from KillerDogeEmpire/master
Updated Animixplay search
This commit is contained in:
commit
4db655bf5b
2 changed files with 188 additions and 163 deletions
|
@ -1,5 +1,5 @@
|
||||||
// use an integer for version numbers
|
// use an integer for version numbers
|
||||||
version = 2
|
version = 3
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
cloudstream {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId
|
||||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||||
|
import org.json.JSONObject
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
|
||||||
|
@ -50,7 +51,7 @@ class Animixplay : MainAPI() {
|
||||||
"$mainUrl/api/search" to "Movie",
|
"$mainUrl/api/search" to "Movie",
|
||||||
)
|
)
|
||||||
|
|
||||||
private var newPagination : String? = null
|
private var newPagination: String? = null
|
||||||
override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
|
override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
|
||||||
val items = mutableListOf<HomePageList>()
|
val items = mutableListOf<HomePageList>()
|
||||||
val paged = page.toString()
|
val paged = page.toString()
|
||||||
|
@ -130,16 +131,22 @@ class Animixplay : MainAPI() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun quickSearch(query: String) = search(query)
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse>? {
|
override suspend fun search(query: String): List<SearchResponse>? {
|
||||||
return app.post(
|
return app.post(
|
||||||
"https://cdn.animixplay.to/api/search",
|
url = "https://v1.ij7p9towl8uj4qafsopjtrjk.workers.dev",
|
||||||
data = mapOf("qfast" to query, "root" to URI(mainUrl).host)
|
referer = mainUrl,
|
||||||
).parsedSafe<Search>()?.result?.let {
|
data = mapOf(
|
||||||
Jsoup.parse(it).select("a").map { elem ->
|
"q2" to query,
|
||||||
val href = elem.attr("href")
|
"origin" to "1",
|
||||||
val title = elem.select("p.name").text()
|
"root" to "animixplay.to",
|
||||||
|
"d" to "gogoanime.tel"
|
||||||
|
)
|
||||||
|
).parsedSafe<FullSearch>()?.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) {
|
newAnimeSearchResponse(title, href, TvType.Anime) {
|
||||||
this.posterUrl = elem.select("img").attr("src")
|
this.posterUrl = elem.select("img").attr("src")
|
||||||
addDubStatus(isDub = title.contains("Dub"))
|
addDubStatus(isDub = title.contains("Dub"))
|
||||||
|
@ -148,188 +155,206 @@ class Animixplay : MainAPI() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse? {
|
override suspend fun quickSearch(query: String): List<SearchResponse>? {
|
||||||
|
return app.post(
|
||||||
val (fixUrl, malId) = if (url.contains("/anime/")) {
|
"https://cdn.animixplay.to/api/search",
|
||||||
listOf(url, Regex("anime/([0-9]+)/?").find(url)?.groupValues?.get(1))
|
data = mapOf("qfast" to query, "root" to URI(mainUrl).host)
|
||||||
} else {
|
).parsedSafe<Search>()?.result?.let {
|
||||||
val malId = app.get(url).text.substringAfterLast("malid = '").substringBefore("';")
|
Jsoup.parse(it).select("a").map { elem ->
|
||||||
listOf("$mainUrl/anime/$malId", malId)
|
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<DataAni>()?.data?.media?.id
|
|
||||||
|
|
||||||
val res = app.get("$mainUrl/assets/mal/$malId.json").parsedSafe<AnimeDetail>()
|
override suspend fun load(url: String): LoadResponse? {
|
||||||
?: throw ErrorLoadingException("Invalid json responses")
|
|
||||||
|
|
||||||
val subEpisodes = mutableListOf<Episode>()
|
val (fixUrl, malId) = if (url.contains("/anime/")) {
|
||||||
val dubEpisodes = mutableListOf<Episode>()
|
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"))
|
val anilistId = app.post(
|
||||||
.parsedSafe<Data>()?.data?.filter { it.type == "GOGO" }?.map { item ->
|
"https://graphql.anilist.co/", data = mapOf(
|
||||||
item.items?.apmap { server ->
|
"query" to "{Media(idMal:$malId,type:ANIME){id}}",
|
||||||
val dataEps =
|
)
|
||||||
app.get(fixUrl(server.url.toString())).document.select("div#epslistplace")
|
).parsedSafe<DataAni>()?.data?.media?.id
|
||||||
.text().trim()
|
|
||||||
Regex("\"([0-9]+)\":\"(\\S+?)\"").findAll(dataEps).toList()
|
val res = app.get("$mainUrl/assets/mal/$malId.json").parsedSafe<AnimeDetail>()
|
||||||
.map { it.groupValues[1] to it.groupValues[2] }.map { (ep, link) ->
|
?: throw ErrorLoadingException("Invalid json responses")
|
||||||
val episode = Episode(fixUrl(link), episode = ep.toInt() + 1)
|
|
||||||
if (server.url?.contains("-dub") == true) {
|
val subEpisodes = mutableListOf<Episode>()
|
||||||
dubEpisodes.add(episode)
|
val dubEpisodes = mutableListOf<Episode>()
|
||||||
} else {
|
|
||||||
subEpisodes.add(episode)
|
app.post("$mainUrl/api/search", data = mapOf("recomended" to "$malId"))
|
||||||
|
.parsedSafe<Data>()?.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<RecResult>()?.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<RecResult>()?.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(
|
private data class IdAni(
|
||||||
data: String,
|
@JsonProperty("id") val id: String? = null,
|
||||||
isCasting: Boolean,
|
)
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
|
|
||||||
val iframe = app.get(data)
|
private data class MediaAni(
|
||||||
val iframeDoc = iframe.document
|
@JsonProperty("Media") val media: IdAni? = null,
|
||||||
|
)
|
||||||
|
|
||||||
argamap({
|
private data class DataAni(
|
||||||
iframeDoc.select(".list-server-items > .linkserver")
|
@JsonProperty("data") val data: MediaAni? = null,
|
||||||
.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 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<Items>? = arrayListOf(),
|
||||||
|
)
|
||||||
|
|
||||||
|
private data class Data(
|
||||||
|
@JsonProperty("data") val data: ArrayList<Episodes>? = arrayListOf(),
|
||||||
|
)
|
||||||
|
|
||||||
private data class IdAni(
|
private data class Aired(
|
||||||
@JsonProperty("id") val id: String? = null,
|
@JsonProperty("from") val from: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
private data class MediaAni(
|
private data class Genres(
|
||||||
@JsonProperty("Media") val media: IdAni? = null,
|
@JsonProperty("name") val name: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
private data class DataAni(
|
private data class RecResult(
|
||||||
@JsonProperty("data") val data: MediaAni? = null,
|
@JsonProperty("recommendations") val recommendations: ArrayList<Recommendations>? = arrayListOf(),
|
||||||
)
|
)
|
||||||
|
|
||||||
private data class Items(
|
private data class Recommendations(
|
||||||
@JsonProperty("url") val url: String? = null,
|
@JsonProperty("mal_id") val malId: String? = null,
|
||||||
@JsonProperty("title") val title: String? = null,
|
@JsonProperty("image_url") val imageUrl: String? = null,
|
||||||
)
|
@JsonProperty("title") val title: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
private data class Episodes(
|
private data class AnimeDetail(
|
||||||
@JsonProperty("type") val type: String? = null,
|
@JsonProperty("title") val title: String? = null,
|
||||||
@JsonProperty("items") val items: ArrayList<Items>? = arrayListOf(),
|
@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<Genres>? = arrayListOf(),
|
||||||
|
)
|
||||||
|
|
||||||
private data class Data(
|
private data class Search(
|
||||||
@JsonProperty("data") val data: ArrayList<Episodes>? = arrayListOf(),
|
@JsonProperty("result") val result: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
private data class Aired(
|
private data class Result(
|
||||||
@JsonProperty("from") val from: String? = null,
|
@JsonProperty("result") val result: ArrayList<Anime> = arrayListOf(),
|
||||||
)
|
@JsonProperty("last") val last: Any? = null,
|
||||||
|
)
|
||||||
|
|
||||||
private data class Genres(
|
private data class Anime(
|
||||||
@JsonProperty("name") val name: String? = null,
|
@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(
|
private data class FullSearch(
|
||||||
@JsonProperty("recommendations") val recommendations: ArrayList<Recommendations>? = 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<Genres>? = arrayListOf(),
|
|
||||||
)
|
|
||||||
|
|
||||||
private data class Search(
|
|
||||||
@JsonProperty("result") val result: String? = null,
|
@JsonProperty("result") val result: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
private data class Result(
|
|
||||||
@JsonProperty("result") val result: ArrayList<Anime> = 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,
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in a new issue