fix(en/kickassanine): Fix extractor & update urls (#3012)

This commit is contained in:
Secozzi 2024-03-06 22:49:35 +00:00 committed by GitHub
parent b16b8b8323
commit 39fba625dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 25 additions and 37 deletions

View File

@ -1,7 +1,7 @@
ext { ext {
extName = 'KickAssAnime' extName = 'KickAssAnime'
extClass = '.KickAssAnime' extClass = '.KickAssAnime'
extVersionCode = 37 extVersionCode = 38
} }
apply from: "$rootDir/common.gradle" apply from: "$rootDir/common.gradle"

View File

@ -37,6 +37,7 @@ import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response import okhttp3.Response
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.util.Locale import java.util.Locale
class KickAssAnime : ConfigurableAnimeSource, AnimeHttpSource() { class KickAssAnime : ConfigurableAnimeSource, AnimeHttpSource() {
@ -53,11 +54,10 @@ class KickAssAnime : ConfigurableAnimeSource, AnimeHttpSource() {
private val preferences: SharedPreferences by lazy { private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000) Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
.clearBaseUrl()
} }
private val json = Json { private val json: Json by injectLazy()
ignoreUnknownKeys = true
}
// ============================== Popular =============================== // ============================== Popular ===============================
override fun popularAnimeRequest(page: Int) = GET("$apiUrl/popular?page=$page") override fun popularAnimeRequest(page: Int) = GET("$apiUrl/popular?page=$page")
@ -290,6 +290,17 @@ class KickAssAnime : ConfigurableAnimeSource, AnimeHttpSource() {
).reversed() ).reversed()
} }
private fun SharedPreferences.clearBaseUrl(): SharedPreferences {
if (getString(PREF_DOMAIN_KEY, "")!! in PREF_DOMAIN_ENTRY_VALUES) {
return this
}
edit()
.remove(PREF_DOMAIN_KEY)
.putString(PREF_DOMAIN_KEY, PREF_DOMAIN_DEFAULT)
.apply()
return this
}
companion object { companion object {
private val SERVERS = arrayOf("DuckStream", "BirdStream", "VidStreaming") private val SERVERS = arrayOf("DuckStream", "BirdStream", "VidStreaming")
@ -323,9 +334,9 @@ class KickAssAnime : ConfigurableAnimeSource, AnimeHttpSource() {
private const val PREF_DOMAIN_KEY = "preferred_domain" private const val PREF_DOMAIN_KEY = "preferred_domain"
private const val PREF_DOMAIN_TITLE = "Preferred domain (requires app restart)" private const val PREF_DOMAIN_TITLE = "Preferred domain (requires app restart)"
private const val PREF_DOMAIN_DEFAULT = "https://kickassanime.am" private const val PREF_DOMAIN_DEFAULT = "https://kaas.to"
private val PREF_DOMAIN_ENTRIES = arrayOf("kickassanime.am", "kaas.to", "kaas.ro") private val PREF_DOMAIN_ENTRIES = arrayOf("kaas.to", "kaas.ro", "kickassanimes.io", "www1.kickassanime.mx")
private val PREF_DOMAIN_ENTRY_VALUES = arrayOf("https://kickassanime.am", "https://kaas.to", "https://kaas.ro") private val PREF_DOMAIN_ENTRY_VALUES = PREF_DOMAIN_ENTRIES.map { "https://$it" }.toTypedArray()
private const val PREF_HOSTER_KEY = "hoster_selection" private const val PREF_HOSTER_KEY = "hoster_selection"
private const val PREF_HOSTER_TITLE = "Enable/Disable Hosts" private const val PREF_HOSTER_TITLE = "Enable/Disable Hosts"

View File

@ -7,9 +7,7 @@ import eu.kanade.tachiyomi.lib.cryptoaes.CryptoAES
import eu.kanade.tachiyomi.lib.cryptoaes.CryptoAES.decodeHex import eu.kanade.tachiyomi.lib.cryptoaes.CryptoAES.decodeHex
import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.parseAs
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import okhttp3.CacheControl
import okhttp3.Headers import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@ -20,27 +18,6 @@ class KickAssAnimeExtractor(
private val json: Json, private val json: Json,
private val headers: Headers, private val headers: Headers,
) { ) {
// Stolen from AniWatch
// Prevent (automatic) caching the .JS file for different episodes, because it
// changes everytime, and a cached old .js will have a invalid AES password,
// invalidating the decryption algorithm.
// We cache it manually when initializing the class.
private val cacheControl = CacheControl.Builder().noStore().build()
private val newClient = client.newBuilder()
.cache(null)
.build()
private val keyMaps by lazy {
buildMap {
put("bird", newClient.newCall(GET("https://raw.githubusercontent.com/enimax-anime/kaas/bird/key.txt", cache = cacheControl)).execute().body.string().toByteArray())
put("duck", newClient.newCall(GET("https://raw.githubusercontent.com/enimax-anime/kaas/duck/key.txt", cache = cacheControl)).execute().body.string().toByteArray())
}
}
private val signaturesMap by lazy {
newClient.newCall(GET("https://raw.githubusercontent.com/enimax-anime/gogo/main/KAA.json", cache = cacheControl)).execute().parseAs<Map<String, List<String>>>()
}
fun videosFromUrl(url: String, name: String): List<Video> { fun videosFromUrl(url: String, name: String): List<Video> {
val host = url.toHttpUrl().host val host = url.toHttpUrl().host
val mid = if (name == "DuckStream") "mid" else "id" val mid = if (name == "DuckStream") "mid" else "id"
@ -51,11 +28,11 @@ class KickAssAnimeExtractor(
val html = client.newCall(GET(url, headers)).execute().body.string() val html = client.newCall(GET(url, headers)).execute().body.string()
val key = when (name) { val key = when (name) {
"VidStreaming" -> keyMaps["duck"]!! "VidStreaming" -> "e13d38099bf562e8b9851a652d2043d3"
"DuckStream" -> keyMaps["duck"]!! "DuckStream" -> "4504447b74641ad972980a6b8ffd7631"
"BirdStream" -> keyMaps["bird"]!! "BirdStream" -> "4b14d0ff625163e3c9c7a47926484bf2"
else -> return emptyList() else -> return emptyList()
} }.toByteArray()
val (sig, timeStamp, route) = getSignature(html, name, query, key) ?: return emptyList() val (sig, timeStamp, route) = getSignature(html, name, query, key) ?: return emptyList()
val sourceUrl = buildString { val sourceUrl = buildString {
@ -127,9 +104,9 @@ class KickAssAnimeExtractor(
private fun getSignature(html: String, server: String, query: String, key: ByteArray): Triple<String, String, String>? { private fun getSignature(html: String, server: String, query: String, key: ByteArray): Triple<String, String, String>? {
val order = when (server) { val order = when (server) {
"VidStreaming" -> signaturesMap["vid"]!! "VidStreaming" -> listOf("IP", "USERAGENT", "ROUTE", "MID", "TIMESTAMP", "KEY")
"DuckStream" -> signaturesMap["duck"]!! "DuckStream" -> listOf("IP", "USERAGENT", "ROUTE", "MID", "TIMESTAMP", "KEY")
"BirdStream" -> signaturesMap["bird"]!! "BirdStream" -> listOf("IP", "USERAGENT", "ROUTE", "MID", "KEY")
else -> return null else -> return null
} }