AllAnime fix
This commit is contained in:
parent
d078283b01
commit
da1dd7c2b8
|
@ -1,5 +1,5 @@
|
||||||
// use an integer for version numbers
|
// use an integer for version numbers
|
||||||
version = 4
|
version = 5
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
cloudstream {
|
||||||
|
@ -22,5 +22,5 @@ cloudstream {
|
||||||
"Anime",
|
"Anime",
|
||||||
)
|
)
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=allanime.site&sz=%size%"
|
iconUrl = "https://www.google.com/s2/favicons?domain=allanime.to&sz=%size%"
|
||||||
}
|
}
|
|
@ -5,20 +5,22 @@ import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
|
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
|
||||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||||
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
||||||
import com.lagradost.cloudstream3.ui.settings.SettingsProviders
|
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||||
|
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
||||||
|
import com.lagradost.cloudstream3.utils.Coroutines.mainWork
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
import com.lagradost.cloudstream3.utils.M3u8Helper
|
import com.lagradost.cloudstream3.utils.M3u8Helper
|
||||||
import com.lagradost.cloudstream3.utils.Qualities
|
import com.lagradost.cloudstream3.utils.Qualities
|
||||||
|
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import org.mozilla.javascript.Context
|
import org.mozilla.javascript.Context
|
||||||
import org.mozilla.javascript.Scriptable
|
import org.mozilla.javascript.Scriptable
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.net.URLDecoder
|
|
||||||
|
|
||||||
|
|
||||||
class AllAnimeProvider : MainAPI() {
|
class AllAnimeProvider : MainAPI() {
|
||||||
override var mainUrl = "https://allanime.site"
|
override var mainUrl = "https://allanime.to"
|
||||||
|
private val apiUrl = "https://api.allanime.co"
|
||||||
override var name = "AllAnime"
|
override var name = "AllAnime"
|
||||||
override val hasQuickSearch = false
|
override val hasQuickSearch = false
|
||||||
override val hasMainPage = true
|
override val hasMainPage = true
|
||||||
|
@ -60,10 +62,10 @@ class AllAnimeProvider : MainAPI() {
|
||||||
@JsonProperty("averageScore") val averageScore: Int?,
|
@JsonProperty("averageScore") val averageScore: Int?,
|
||||||
@JsonProperty("description") val description: String?,
|
@JsonProperty("description") val description: String?,
|
||||||
@JsonProperty("status") val status: String?,
|
@JsonProperty("status") val status: String?,
|
||||||
@JsonProperty("banner") val banner : String?,
|
@JsonProperty("banner") val banner: String?,
|
||||||
@JsonProperty("episodeDuration") val episodeDuration : Int?,
|
@JsonProperty("episodeDuration") val episodeDuration: Int?,
|
||||||
@JsonProperty("prevideos") val prevideos : List<String> = emptyList(),
|
@JsonProperty("prevideos") val prevideos: List<String> = emptyList(),
|
||||||
)
|
)
|
||||||
|
|
||||||
private data class AvailableEpisodes(
|
private data class AvailableEpisodes(
|
||||||
@JsonProperty("sub") val sub: Int,
|
@JsonProperty("sub") val sub: Int,
|
||||||
|
@ -209,12 +211,13 @@ class AllAnimeProvider : MainAPI() {
|
||||||
@JsonProperty("raw") val raw: List<String>
|
@JsonProperty("raw") val raw: List<String>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse? {
|
override suspend fun load(url: String): LoadResponse? {
|
||||||
val rhino = Context.enter()
|
val (rhino, scope) = mainWork {
|
||||||
rhino.initSafeStandardObjects()
|
val rhino = Context.enter()
|
||||||
rhino.optimizationLevel = -1
|
rhino.optimizationLevel = -1
|
||||||
val scope: Scriptable = rhino.initSafeStandardObjects()
|
val scope: Scriptable = rhino.initSafeStandardObjects()
|
||||||
|
rhino to scope
|
||||||
|
}
|
||||||
|
|
||||||
val html = app.get(url).text
|
val html = app.get(url).text
|
||||||
val soup = Jsoup.parse(html)
|
val soup = Jsoup.parse(html)
|
||||||
|
@ -229,8 +232,10 @@ class AllAnimeProvider : MainAPI() {
|
||||||
const returnValue = JSON.stringify(window.__NUXT__.fetch[0].show)
|
const returnValue = JSON.stringify(window.__NUXT__.fetch[0].show)
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
|
|
||||||
rhino.evaluateString(scope, js, "JavaScript", 1, null)
|
val jsEval = mainWork {
|
||||||
val jsEval = scope.get("returnValue", scope) ?: return null
|
rhino.evaluateString(scope, js, "JavaScript", 1, null)
|
||||||
|
scope.get("returnValue", scope) ?: return@mainWork null
|
||||||
|
} ?: return null
|
||||||
|
|
||||||
val showData = parseJson<Edges>(jsEval as String)
|
val showData = parseJson<Edges>(jsEval as String)
|
||||||
|
|
||||||
|
@ -240,13 +245,15 @@ class AllAnimeProvider : MainAPI() {
|
||||||
|
|
||||||
val episodes = showData.availableEpisodes.let {
|
val episodes = showData.availableEpisodes.let {
|
||||||
if (it == null) return@let Pair(null, null)
|
if (it == null) return@let Pair(null, null)
|
||||||
|
if (showData.Id == null) return@let Pair(null, null)
|
||||||
|
|
||||||
Pair(if (it.sub != 0) ((1..it.sub).map { epNum ->
|
Pair(if (it.sub != 0) ((1..it.sub).map { epNum ->
|
||||||
Episode(
|
Episode(
|
||||||
"$mainUrl/anime/${showData.Id}/episodes/sub/$epNum", episode = epNum
|
AllAnimeLoadData(showData.Id, "sub", epNum).toJson(), episode = epNum
|
||||||
)
|
)
|
||||||
}) else null, if (it.dub != 0) ((1..it.dub).map { epNum ->
|
}) else null, if (it.dub != 0) ((1..it.dub).map { epNum ->
|
||||||
Episode(
|
Episode(
|
||||||
"$mainUrl/anime/${showData.Id}/episodes/dub/$epNum", episode = epNum
|
AllAnimeLoadData(showData.Id, "dub", epNum).toJson(), episode = epNum
|
||||||
)
|
)
|
||||||
}) else null)
|
}) else null)
|
||||||
}
|
}
|
||||||
|
@ -279,7 +286,8 @@ class AllAnimeProvider : MainAPI() {
|
||||||
tags = showData.genres
|
tags = showData.genres
|
||||||
year = showData.airedStart?.year
|
year = showData.airedStart?.year
|
||||||
duration = showData.episodeDuration?.div(60_000)
|
duration = showData.episodeDuration?.div(60_000)
|
||||||
addTrailer(showData.prevideos.filter { it.isNotBlank() }.map { "https://www.youtube.com/watch?v=$it" })
|
addTrailer(showData.prevideos.filter { it.isNotBlank() }
|
||||||
|
.map { "https://www.youtube.com/watch?v=$it" })
|
||||||
|
|
||||||
addEpisodes(DubStatus.Subbed, episodes.first)
|
addEpisodes(DubStatus.Subbed, episodes.first)
|
||||||
addEpisodes(DubStatus.Dubbed, episodes.second)
|
addEpisodes(DubStatus.Dubbed, episodes.second)
|
||||||
|
@ -299,6 +307,7 @@ class AllAnimeProvider : MainAPI() {
|
||||||
"https://videobin.co/",
|
"https://videobin.co/",
|
||||||
"https://ok.ru",
|
"https://ok.ru",
|
||||||
"https://streamlare.com",
|
"https://streamlare.com",
|
||||||
|
"https://gembedhd.com",
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun embedIsBlacklisted(url: String): Boolean {
|
private fun embedIsBlacklisted(url: String): Boolean {
|
||||||
|
@ -352,74 +361,77 @@ class AllAnimeProvider : MainAPI() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class AllAnimeLoadData(
|
||||||
|
val hash: String,
|
||||||
|
val dubStatus: String,
|
||||||
|
val episode: Int
|
||||||
|
)
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
override suspend fun loadLinks(
|
||||||
data: String,
|
data: String,
|
||||||
isCasting: Boolean,
|
isCasting: Boolean,
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
): Boolean {
|
): Boolean {
|
||||||
|
val loadData = parseJson<AllAnimeLoadData>(data)
|
||||||
var apiEndPoint =
|
var apiEndPoint =
|
||||||
parseJson<ApiEndPoint>(app.get("$mainUrl/getVersion").text).episodeIframeHead
|
parseJson<ApiEndPoint>(app.get("$mainUrl/getVersion").text).episodeIframeHead
|
||||||
if (apiEndPoint.endsWith("/")) apiEndPoint =
|
if (apiEndPoint.endsWith("/")) apiEndPoint =
|
||||||
apiEndPoint.slice(0 until apiEndPoint.length - 1)
|
apiEndPoint.slice(0 until apiEndPoint.length - 1)
|
||||||
|
|
||||||
val html = app.get(data).text
|
val apiUrl =
|
||||||
|
"""$apiUrl/allanimeapi?variables={"showId":"${loadData.hash}","translationType":"${loadData.dubStatus}","episodeString":"${loadData.episode}"}&extensions={"persistedQuery":{"version":1,"sha256Hash":"1f0a5d6c9ce6cd3127ee4efd304349345b0737fbf5ec33a60bbc3d18e3bb7c61"}}"""
|
||||||
|
val apiResponse = app.get(apiUrl).parsed<LinksQuery>()
|
||||||
|
|
||||||
val sources = Regex("""sourceUrl[:=]"(.+?)"""").findAll(html).toList()
|
apiResponse.data?.episode?.sourceUrls?.apmap { source ->
|
||||||
.map { URLDecoder.decode(it.destructured.component1().sanitize(), "UTF-8") }
|
|
||||||
sources.apmap {
|
|
||||||
safeApiCall {
|
safeApiCall {
|
||||||
var link = it.replace(" ", "%20")
|
val link = source.sourceUrl?.replace(" ", "%20") ?: return@safeApiCall
|
||||||
if (URI(link).isAbsolute || link.startsWith("//")) {
|
if (URI(link).isAbsolute || link.startsWith("//")) {
|
||||||
if (link.startsWith("//")) link = "https:$it"
|
val fixedLink = if (link.startsWith("//")) "https:$link" else link
|
||||||
|
val sourceName = source.sourceName ?: URI(link).host
|
||||||
|
|
||||||
if (Regex("""streaming\.php\?""").matches(link)) {
|
if (embedIsBlacklisted(fixedLink)) {
|
||||||
// for now ignore
|
loadExtractor(fixedLink, subtitleCallback, callback)
|
||||||
} else if (!embedIsBlacklisted(link)) {
|
} else if (URI(fixedLink).path.contains(".m3u")) {
|
||||||
if (URI(link).path.contains(".m3u")) {
|
getM3u8Qualities(fixedLink, mainUrl, sourceName).forEach(callback)
|
||||||
getM3u8Qualities(link, data, URI(link).host).forEach(callback)
|
} else {
|
||||||
|
callback(
|
||||||
|
ExtractorLink(
|
||||||
|
name,
|
||||||
|
sourceName,
|
||||||
|
fixedLink,
|
||||||
|
mainUrl,
|
||||||
|
Qualities.P1080.value,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val fixedLink = apiEndPoint + URI(link).path + ".json?" + URI(link).query
|
||||||
|
val links = app.get(fixedLink).parsedSafe<AllAnimeVideoApiResponse>()?.links
|
||||||
|
?: emptyList()
|
||||||
|
links.forEach { server ->
|
||||||
|
if (server.hls != null && server.hls) {
|
||||||
|
getM3u8Qualities(
|
||||||
|
server.link,
|
||||||
|
"$apiEndPoint/player?uri=" + (if (URI(server.link).host.isNotEmpty()) server.link else apiEndPoint + URI(
|
||||||
|
server.link
|
||||||
|
).path),
|
||||||
|
server.resolutionStr
|
||||||
|
).forEach(callback)
|
||||||
} else {
|
} else {
|
||||||
callback(
|
callback(
|
||||||
ExtractorLink(
|
ExtractorLink(
|
||||||
"AllAnime - " + URI(link).host,
|
"AllAnime - " + URI(server.link).host,
|
||||||
"",
|
server.resolutionStr,
|
||||||
link,
|
|
||||||
data,
|
|
||||||
Qualities.P1080.value,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
link = apiEndPoint + URI(link).path + ".json?" + URI(link).query
|
|
||||||
val response = app.get(link)
|
|
||||||
|
|
||||||
if (response.code < 400) {
|
|
||||||
val links = parseJson<AllAnimeVideoApiResponse>(response.text).links
|
|
||||||
links.forEach { server ->
|
|
||||||
if (server.hls != null && server.hls) {
|
|
||||||
getM3u8Qualities(
|
|
||||||
server.link,
|
server.link,
|
||||||
"$apiEndPoint/player?uri=" + (if (URI(server.link).host.isNotEmpty()) server.link else apiEndPoint + URI(
|
"$apiEndPoint/player?uri=" + (if (URI(server.link).host.isNotEmpty()) server.link else apiEndPoint + URI(
|
||||||
server.link
|
server.link
|
||||||
).path),
|
).path),
|
||||||
server.resolutionStr
|
Qualities.P1080.value,
|
||||||
).forEach(callback)
|
false
|
||||||
} else {
|
|
||||||
callback(
|
|
||||||
ExtractorLink(
|
|
||||||
"AllAnime - " + URI(server.link).host,
|
|
||||||
server.resolutionStr,
|
|
||||||
server.link,
|
|
||||||
"$apiEndPoint/player?uri=" + (if (URI(server.link).host.isNotEmpty()) server.link else apiEndPoint + URI(
|
|
||||||
server.link
|
|
||||||
).path),
|
|
||||||
Qualities.P1080.value,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
package com.lagradost
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
|
|
||||||
|
data class LinksQuery(
|
||||||
|
@JsonProperty("data") val data: LinkData? = LinkData()
|
||||||
|
)
|
||||||
|
|
||||||
|
data class LinkData(
|
||||||
|
@JsonProperty("episode") val episode: Episode? = Episode()
|
||||||
|
)
|
||||||
|
|
||||||
|
data class SourceUrls(
|
||||||
|
@JsonProperty("sourceUrl") val sourceUrl: String? = null,
|
||||||
|
@JsonProperty("priority") val priority: Int? = null,
|
||||||
|
@JsonProperty("sourceName") val sourceName: String? = null,
|
||||||
|
@JsonProperty("type") val type: String? = null,
|
||||||
|
@JsonProperty("className") val className: String? = null,
|
||||||
|
@JsonProperty("streamerId") val streamerId: String? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Episode(
|
||||||
|
@JsonProperty("episodeString") val episodeString: String? = null,
|
||||||
|
// @JsonProperty("uploadDate" ) val uploadDate : UploadDate? = UploadDate(),
|
||||||
|
@JsonProperty("sourceUrls") val sourceUrls: ArrayList<SourceUrls> = arrayListOf(),
|
||||||
|
@JsonProperty("thumbnail") val thumbnail: String? = null,
|
||||||
|
@JsonProperty("notes") val notes: String? = null,
|
||||||
|
// @JsonProperty("show" ) val show : Show? = Show(),
|
||||||
|
@JsonProperty("pageStatus") val pageStatus: PageStatus? = PageStatus(),
|
||||||
|
@JsonProperty("episodeInfo") val episodeInfo: EpisodeInfo? = EpisodeInfo(),
|
||||||
|
@JsonProperty("versionFix") val versionFix: String? = null,
|
||||||
|
@JsonProperty("__typename") val _typename: String? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
data class EpisodeInfo(
|
||||||
|
@JsonProperty("notes") val notes: String? = null,
|
||||||
|
@JsonProperty("thumbnails") val thumbnails: ArrayList<String> = arrayListOf(),
|
||||||
|
@JsonProperty("vidInforssub") val vidInforssub: VidInforssub? = VidInforssub(),
|
||||||
|
// @JsonProperty("uploadDates" ) val uploadDates : UploadDates? = UploadDates(),
|
||||||
|
@JsonProperty("vidInforsdub") val vidInforsdub: String? = null,
|
||||||
|
@JsonProperty("vidInforsraw") val vidInforsraw: String? = null,
|
||||||
|
@JsonProperty("description") val description: String? = null,
|
||||||
|
@JsonProperty("__typename") val _typename: String? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
data class VidInforssub(
|
||||||
|
@JsonProperty("vidResolution") val vidResolution: Int? = null,
|
||||||
|
@JsonProperty("vidPath") val vidPath: String? = null,
|
||||||
|
@JsonProperty("vidSize") val vidSize: Int? = null,
|
||||||
|
@JsonProperty("vidDuration") val vidDuration: Double? = null
|
||||||
|
)
|
Loading…
Reference in New Issue