aniage: Reformat code and fix parsing ID

This commit is contained in:
CakesTwix 2023-12-12 20:38:15 +02:00
parent 28a5cb4326
commit 3c61de375b
Signed by: CakesTwix
GPG key ID: 7B11051D5CE19825
2 changed files with 169 additions and 121 deletions

View file

@ -1,5 +1,5 @@
// use an integer for version numbers // use an integer for version numbers
version = 10 version = 11
dependencies{ dependencies{
implementation("com.google.code.gson:gson:2.9.0") implementation("com.google.code.gson:gson:2.9.0")

View file

@ -38,11 +38,12 @@ class AniageProvider : MainAPI() {
override val hasMainPage = true override val hasMainPage = true
override var lang = "uk" override var lang = "uk"
override val hasDownloadSupport = true override val hasDownloadSupport = true
override val supportedTypes = setOf( override val supportedTypes =
TvType.Anime, setOf(
TvType.AnimeMovie, TvType.Anime,
TvType.OVA, TvType.AnimeMovie,
) TvType.OVA,
)
private val apiUrl = "https://master.api.aniage.net" private val apiUrl = "https://master.api.aniage.net"
private val findUrl = "https://finder-master.api.aniage.net/?query=" private val findUrl = "https://finder-master.api.aniage.net/?query="
@ -50,39 +51,41 @@ class AniageProvider : MainAPI() {
private val videoCdn = "https://aniage-video-stream.b-cdn.net/" private val videoCdn = "https://aniage-video-stream.b-cdn.net/"
private val pageSize = 30 private val pageSize = 30
private val listEpisodeModel = object : TypeToken<List<EpisodesModel>>() { }.type private val listEpisodeModel = object : TypeToken<List<EpisodesModel>>() {}.type
private val listTeamsModel = object : TypeToken<List<TeamsModel>>() { }.type private val listTeamsModel = object : TypeToken<List<TeamsModel>>() {}.type
private val listPageModel = object : TypeToken<List<PageProps>>() { }.type private val listPageModel = object : TypeToken<List<PageProps>>() {}.type
// Sections // Sections
override val mainPage = mainPageOf( override val mainPage =
mainUrl to "Нове", mainPageOf(
mainUrl to "Повнометражне", mainUrl to "Нове",
mainUrl to "ONA", mainUrl to "Повнометражне",
mainUrl to "OVA", mainUrl to "ONA",
mainUrl to "SPECIAL", mainUrl to "OVA",
mainUrl to "ТБ-Серіал", mainUrl to "SPECIAL",
mainUrl to "ТБ-Спешл", mainUrl to "ТБ-Серіал",
mainUrl to "Короткометражне", mainUrl to "ТБ-Спешл",
) mainUrl to "Короткометражне",
)
// Done // Done
override suspend fun getMainPage( override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
page: Int,
request: MainPageRequest
): HomePageResponse {
val body = JSONObject() val body = JSONObject()
val cleanup = with(request.name){ val cleanup =
when{ with(request.name) {
this == "Нове" -> JSONArray() when {
else -> JSONArray().put(JSONObject() this == "Нове" -> JSONArray()
.put("property","type") else ->
.put("type", "=") JSONArray()
.put("value", JSONArray().put(this)) .put(
) JSONObject()
.put("property", "type")
.put("type", "=")
.put("value", JSONArray().put(this))
)
}
} }
}
body.put("cleanup", cleanup) body.put("cleanup", cleanup)
val orderBody = JSONObject() val orderBody = JSONObject()
@ -93,102 +96,126 @@ class AniageProvider : MainAPI() {
body.put("page", page) body.put("page", page)
body.put("pageSize", pageSize) body.put("pageSize", pageSize)
val document = app.post("$apiUrl/v2/anime/find", val document = app.post("$apiUrl/v2/anime/find", json = body).text
json = body
).text
val parsedJSON = Gson().fromJson(document, FindModel::class.java) val parsedJSON = Gson().fromJson(document, FindModel::class.java)
// Log.d("CakesTwix-Debug", parsedJSON.data[0].title) // Log.d("CakesTwix-Debug", parsedJSON.data[0].title)
val homeList = parsedJSON.data.map { val homeList =
newAnimeSearchResponse(it.title, it.id, TvType.Anime) { parsedJSON.data.map {
this.posterUrl = "$imageUrl/main/${it.posterId}?width=296" newAnimeSearchResponse(it.title, it.id, TvType.Anime) {
addDubStatus(isDub = true, it.episodes) this.posterUrl = "$imageUrl/main/${it.posterId}?width=296"
this.otherName = it.alternativeTitle addDubStatus(isDub = true, it.episodes)
this.otherName = it.alternativeTitle
}
} }
}
// Log.d("CakesTwix-Debug", "$cdnUrl${parsedJSON.data[1].posterId}") // Log.d("CakesTwix-Debug", "$cdnUrl${parsedJSON.data[1].posterId}")
return newHomePageResponse(request.name, homeList) return newHomePageResponse(request.name, homeList)
} }
override suspend fun search(query: String): List<SearchResponse> { override suspend fun search(query: String): List<SearchResponse> {
val animeJSON = Gson().fromJson<List<PageProps>>(app.get("$findUrl$query").text, listPageModel) val animeJSON =
val findList = animeJSON.map { Gson().fromJson<List<PageProps>>(app.get("$findUrl$query").text, listPageModel)
newAnimeSearchResponse(it.title, it.id, TvType.Anime) { val findList =
this.posterUrl = "$imageUrl/main/${it.posterId}?width=296" animeJSON.map {
addDubStatus(isDub = true, it.episodes) newAnimeSearchResponse(it.title, it.id, TvType.Anime) {
this.otherName = it.alternativeTitle this.posterUrl = "$imageUrl/main/${it.posterId}?width=296"
addDubStatus(isDub = true, it.episodes)
this.otherName = it.alternativeTitle
}
} }
}
return findList return findList
} }
// Detailed information // Detailed information
override suspend fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
val animeID = url.replace("$mainUrl/", "") val animeID = url.replace("$mainUrl/watch?wid=", "").replace("$mainUrl/", "")
val document = app.get("$mainUrl/$animeID").document val document = app.get("$mainUrl/watch/$animeID").document
val jsonObject = JSONObject(document.selectFirst("script[type*=application/json]")!!.html()) val jsonObject = JSONObject(document.selectFirst("script[type*=application/json]")!!.html())
val buildId = jsonObject.getString("buildId") val buildId = jsonObject.getString("buildId")
// https://www.aniage.net/_next/data/IfKYt_B-o41irAex5hZoV/watch.json?wid=96dcb9ce-e4bc-4248-8ed3-29c3d14aedfc // https://www.aniage.net/_next/data/IfKYt_B-o41irAex5hZoV/watch.json?wid=96dcb9ce-e4bc-4248-8ed3-29c3d14aedfc
// Log.d("CakesTwix-Debug", "$mainUrl/_next/data/$buildId/watch.json?wid=$animeID") // Log.d("CakesTwix-Debug", "$mainUrl/_next/data/$buildId/watch.json?wid=$animeID")
val animeJSON = Gson().fromJson(app.get("$mainUrl/_next/data/$buildId/watch.json?wid=$animeID").text, AnimeDetail::class.java) val animeJSON =
Gson()
.fromJson(
app.get("$mainUrl/_next/data/$buildId/watch.json?wid=$animeID").text,
AnimeDetail::class.java
)
// Log.d("CakesTwix-Debug", animeJSON.pageProps.title) // Log.d("CakesTwix-Debug", animeJSON.pageProps.title)
val showStatus = with(animeJSON.pageProps.titleStatus){ val showStatus =
when{ with(animeJSON.pageProps.titleStatus) {
contains("Онгоїнг") -> ShowStatus.Ongoing when {
contains("Вийшло") -> ShowStatus.Completed contains("Онгоїнг") -> ShowStatus.Ongoing
else -> null contains("Вийшло") -> ShowStatus.Completed
else -> null
}
} }
}
val tvType = with(animeJSON.pageProps.type){ val tvType =
when{ with(animeJSON.pageProps.type) {
contains("ТБ-Серіал") -> TvType.Anime when {
contains("ТБ-Спешл") -> TvType.Anime contains("ТБ-Серіал") -> TvType.Anime
contains("OVA") -> TvType.OVA contains("ТБ-Спешл") -> TvType.Anime
contains("SPECIAL") -> TvType.OVA contains("OVA") -> TvType.OVA
contains("ONA") -> TvType.OVA contains("SPECIAL") -> TvType.OVA
contains("Повнометражне") -> TvType.AnimeMovie contains("ONA") -> TvType.OVA
contains("Короткометражне") -> TvType.AnimeMovie contains("Повнометражне") -> TvType.AnimeMovie
else -> TvType.Anime contains("Короткометражне") -> TvType.AnimeMovie
else -> TvType.Anime
}
} }
}
val trailer = with(animeJSON.pageProps.trailerUrl){ val trailer =
when{ with(animeJSON.pageProps.trailerUrl) {
this.isNullOrEmpty() -> null when {
contains("https://iframe.mediadelivery.net/embed") -> this.isNullOrEmpty() -> null
app.get(this).document.select("source[type*=application/x-mpegURL]").attr("src") contains("https://iframe.mediadelivery.net/embed") ->
else -> app.get(this)
null .document
.select("source[type*=application/x-mpegURL]")
.attr("src")
else -> null
}
} }
}
// Episodes // Episodes
val episodes = mutableListOf<Episode>() val episodes = mutableListOf<Episode>()
// Log.d("CakesTwix-Debug", app.get("https://master.api.aniage.net/anime/episodes?animeId=$animeID&page=1&pageSize=30&sortOrder=ASC&teamId=${animeJSON.pageProps.teams[0].teamId}&volume=1").url) // Log.d("CakesTwix-Debug",
if(animeJSON.pageProps.teams.isNotEmpty()){ // app.get("https://master.api.aniage.net/anime/episodes?animeId=$animeID&page=1&pageSize=30&sortOrder=ASC&teamId=${animeJSON.pageProps.teams[0].teamId}&volume=1").url)
Gson().fromJson<List<EpisodesModel>>(app.get("$apiUrl/anime/episodes?animeId=$animeID&page=1&pageSize=30&sortOrder=ASC&teamId=${animeJSON.pageProps.teams[0].teamId}&volume=1").text, listEpisodeModel).map { if (animeJSON.pageProps.teams.isNotEmpty()) {
val episodeName = if(it.title == "." || it.title == it.episodeNum.toString()) "Серія ${it.episodeNum}" else it.title Gson()
episodes.add(Episode .fromJson<List<EpisodesModel>>(
( app.get(
"${it.animeId}, ${it.episodeNum}", "$apiUrl/anime/episodes?animeId=$animeID&page=1&pageSize=30&sortOrder=ASC&teamId=${animeJSON.pageProps.teams[0].teamId}&volume=1"
episodeName,
episode = it.episodeNum,
// posterUrl = "$imageUrl/main/${it.previewPath}",
) )
.text,
listEpisodeModel
) )
return@map .map {
} val episodeName =
if (it.title == "." || it.title == it.episodeNum.toString())
"Серія ${it.episodeNum}"
else it.title
episodes.add(
Episode(
"${it.animeId}, ${it.episodeNum}",
episodeName,
episode = it.episodeNum,
// posterUrl = "$imageUrl/main/${it.previewPath}",
)
)
return@map
}
} }
return newAnimeLoadResponse( return newAnimeLoadResponse(
animeJSON.pageProps.title, animeJSON.pageProps.title,
"$mainUrl/watch?wid=$animeID", "$mainUrl/watch?wid=$animeID",
tvType, tvType,
) { ) {
this.posterUrl = "$imageUrl/main/${animeJSON.pageProps.posterId}?optimize=image&width=296" this.posterUrl =
"$imageUrl/main/${animeJSON.pageProps.posterId}?optimize=image&width=296"
this.engName = animeJSON.pageProps.alternativeTitle this.engName = animeJSON.pageProps.alternativeTitle
this.tags = animeJSON.pageProps.genres.map { it } this.tags = animeJSON.pageProps.genres.map { it }
this.plot = animeJSON.pageProps.description this.plot = animeJSON.pageProps.description
@ -215,42 +242,64 @@ class AniageProvider : MainAPI() {
val jsonObject = JSONObject(document.selectFirst("script[type*=application/json]")!!.html()) val jsonObject = JSONObject(document.selectFirst("script[type*=application/json]")!!.html())
val buildId = jsonObject.getString("buildId") val buildId = jsonObject.getString("buildId")
val animeJSON = Gson().fromJson(app.get("$mainUrl/_next/data/$buildId/watch.json?wid=${dataList[0]}").text, AnimeDetail::class.java) val animeJSON =
Gson()
.fromJson(
app.get("$mainUrl/_next/data/$buildId/watch.json?wid=${dataList[0]}").text,
AnimeDetail::class.java
)
var stringTeam = "$apiUrl/anime/teams/by-ids?" var stringTeam = "$apiUrl/anime/teams/by-ids?"
animeJSON.pageProps.teams.map { teams -> animeJSON.pageProps.teams.map { teams -> stringTeam += "ids=${teams.teamId}&" }
stringTeam += "ids=${teams.teamId}&"
}
// /anime/teams/by-ids?ids=e6bff5dc-354b-4fda-98b3-c29c12931070&ids=31d156c3-1596-4dd0-8736-a01f7793c5de // /anime/teams/by-ids?ids=e6bff5dc-354b-4fda-98b3-c29c12931070&ids=31d156c3-1596-4dd0-8736-a01f7793c5de
// /anime/teams/by-ids?ids=e6bff5dc-354b-4fda-98b3-c29c12931070ids=31d156c3-1596-4dd0-8736-a01f7793c5deids=c7ea3994-2841-4798-b39d-5d9389409f59 // /anime/teams/by-ids?ids=e6bff5dc-354b-4fda-98b3-c29c12931070ids=31d156c3-1596-4dd0-8736-a01f7793c5deids=c7ea3994-2841-4798-b39d-5d9389409f59
// For names // For names
Gson().fromJson<List<TeamsModel>>(app.get(stringTeam).text, listTeamsModel).forEach { teamName -> Gson().fromJson<List<TeamsModel>>(app.get(stringTeam).text, listTeamsModel).forEach {
Gson().fromJson<List<EpisodesModel>>(app.get("$apiUrl/anime/episodes?animeId=${dataList[0]}&page=1&pageSize=30&sortOrder=ASC&teamId=${teamName.id}&volume=1").text, listEpisodeModel).map { teamName ->
if(it.episodeNum == dataList[1].toIntOrNull()){ Gson()
when{ .fromJson<List<EpisodesModel>>(
it.playPath != null -> app.get(
M3u8Helper.generateM3u8( "$apiUrl/anime/episodes?animeId=${dataList[0]}&page=1&pageSize=30&sortOrder=ASC&teamId=${teamName.id}&volume=1"
source = teamName.name, )
streamUrl = app.get(it.playPath).document.select("source").attr("src"), .text,
referer = mainUrl listEpisodeModel
).forEach(callback) )
.map {
it.s3VideoSource != null -> if (it.episodeNum == dataList[1].toIntOrNull()) {
M3u8Helper.generateM3u8( when {
source = teamName.name, it.playPath != null ->
streamUrl = "$videoCdn${it.s3VideoSource.playlistPath}", M3u8Helper.generateM3u8(
referer = apiUrl source = teamName.name,
).forEach(callback) streamUrl =
it.videoSource != null -> app.get(it.playPath)
M3u8Helper.generateM3u8( .document
source = teamName.name, .select("source")
streamUrl = app.get(it.videoSource.playPath).document.select("source").attr("src"), .attr("src"),
referer = mainUrl referer = mainUrl
).forEach(callback) )
.forEach(callback)
it.s3VideoSource != null ->
M3u8Helper.generateM3u8(
source = teamName.name,
streamUrl = "$videoCdn${it.s3VideoSource.playlistPath}",
referer = apiUrl
)
.forEach(callback)
it.videoSource != null ->
M3u8Helper.generateM3u8(
source = teamName.name,
streamUrl =
app.get(it.videoSource.playPath)
.document
.select("source")
.attr("src"),
referer = mainUrl
)
.forEach(callback)
}
} }
} }
}
} }
return true return true
@ -258,11 +307,10 @@ class AniageProvider : MainAPI() {
private fun extractIntFromString(string: String): Int? { private fun extractIntFromString(string: String): Int? {
val value = Regex("(\\d+)").findAll(string).lastOrNull() ?: return null val value = Regex("(\\d+)").findAll(string).lastOrNull() ?: return null
if(value.value[0].toString() == "0"){ if (value.value[0].toString() == "0") {
return value.value.drop(1).toIntOrNull() return value.value.drop(1).toIntOrNull()
} }
return value.value.toIntOrNull() return value.value.toIntOrNull()
} }
} }