parent
76168819ae
commit
1bbc02413e
2 changed files with 27 additions and 84 deletions
|
@ -1,7 +1,7 @@
|
|||
ext {
|
||||
extName = 'Aniwave'
|
||||
extClass = '.Aniwave'
|
||||
extVersionCode = 73
|
||||
extVersionCode = 72
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
|
|
@ -2,10 +2,7 @@ package eu.kanade.tachiyomi.animeextension.en.nineanime
|
|||
|
||||
import android.app.Application
|
||||
import android.content.SharedPreferences
|
||||
import android.util.Log
|
||||
import android.webkit.URLUtil
|
||||
import android.widget.Toast
|
||||
import androidx.preference.EditTextPreference
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.MultiSelectListPreference
|
||||
import androidx.preference.PreferenceScreen
|
||||
|
@ -41,12 +38,7 @@ class Aniwave : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
override val id: Long = 98855593379717478
|
||||
|
||||
override val baseUrl by lazy {
|
||||
val customDomain = preferences.getString(PREF_CUSTOM_DOMAIN_KEY, null)
|
||||
if (customDomain.isNullOrBlank()) {
|
||||
preferences.getString(PREF_DOMAIN_KEY, PREF_DOMAIN_DEFAULT)!!
|
||||
} else {
|
||||
customDomain
|
||||
}
|
||||
}
|
||||
|
||||
override val lang = "en"
|
||||
|
@ -97,7 +89,7 @@ class Aniwave : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
|
||||
val filters = AniwaveFilters.getSearchParameters(filters)
|
||||
|
||||
val vrf = if (query.isNotBlank()) utils.vrfEncrypt(ENCRYPTION_KEY, query) else ""
|
||||
val vrf = if (query.isNotBlank()) utils.vrfEncrypt(KEY_ENCRYPT, query) else ""
|
||||
var url = "$baseUrl/filter?keyword=$query"
|
||||
|
||||
if (filters.genre.isNotBlank()) url += filters.genre
|
||||
|
@ -124,18 +116,15 @@ class Aniwave : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
|
||||
// =========================== Anime Details ============================
|
||||
|
||||
override fun animeDetailsParse(document: Document): SAnime {
|
||||
val anime = SAnime.create()
|
||||
val newDocument = resolveSearchAnime(anime, document)
|
||||
anime.apply {
|
||||
title = newDocument.select("h1.title").text()
|
||||
genre = newDocument.select("div:contains(Genre) > span > a").joinToString { it.text() }
|
||||
description = newDocument.select("div.synopsis > div.shorting > div.content").text()
|
||||
author = newDocument.select("div:contains(Studio) > span > a").text()
|
||||
status = parseStatus(newDocument.select("div:contains(Status) > span").text())
|
||||
override fun animeDetailsParse(document: Document): SAnime = SAnime.create().apply {
|
||||
title = document.select("h1.title").text()
|
||||
genre = document.select("div:contains(Genre) > span > a").joinToString { it.text() }
|
||||
description = document.select("div.synopsis > div.shorting > div.content").text()
|
||||
author = document.select("div:contains(Studio) > span > a").text()
|
||||
status = parseStatus(document.select("div:contains(Status) > span").text())
|
||||
|
||||
val altName = "Other name(s): "
|
||||
newDocument.select("h1.title").attr("data-jp").let {
|
||||
document.select("h1.title").attr("data-jp").let {
|
||||
if (it.isNotBlank()) {
|
||||
description = when {
|
||||
description.isNullOrBlank() -> altName + it
|
||||
|
@ -144,19 +133,13 @@ class Aniwave : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
}
|
||||
}
|
||||
}
|
||||
return anime
|
||||
}
|
||||
|
||||
// ============================== Episodes ==============================
|
||||
|
||||
override fun episodeListRequest(anime: SAnime): Request {
|
||||
Log.i(name, "episodeListRequest")
|
||||
val response = client.newCall(GET(baseUrl + anime.url)).execute()
|
||||
var document = response.asJsoup()
|
||||
document = resolveSearchAnime(anime, document)
|
||||
val id = document.selectFirst("div[data-id]")?.attr("data-id") ?: throw Exception("ID not found")
|
||||
|
||||
val vrf = utils.vrfEncrypt(ENCRYPTION_KEY, id)
|
||||
val id = client.newCall(GET(baseUrl + anime.url)).execute().asJsoup()
|
||||
.selectFirst("div[data-id]")!!.attr("data-id")
|
||||
val vrf = utils.vrfEncrypt(KEY_ENCRYPT, id)
|
||||
|
||||
val listHeaders = headers.newBuilder().apply {
|
||||
add("Accept", "application/json, text/javascript, */*; q=0.01")
|
||||
|
@ -212,7 +195,7 @@ class Aniwave : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
|
||||
override fun videoListRequest(episode: SEpisode): Request {
|
||||
val ids = episode.url.substringBefore("&")
|
||||
val vrf = utils.vrfEncrypt(ENCRYPTION_KEY, ids)
|
||||
val vrf = utils.vrfEncrypt(KEY_ENCRYPT, ids)
|
||||
val url = "/ajax/server/list/$ids?vrf=$vrf"
|
||||
val epurl = episode.url.substringAfter("epurl=")
|
||||
|
||||
|
@ -265,7 +248,7 @@ class Aniwave : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
private val mp4uploadExtractor by lazy { Mp4uploadExtractor(client) }
|
||||
|
||||
private fun extractVideo(server: VideoData, epUrl: String): List<Video> {
|
||||
val vrf = utils.vrfEncrypt(ENCRYPTION_KEY, server.serverId)
|
||||
val vrf = utils.vrfEncrypt(KEY_ENCRYPT, server.serverId)
|
||||
|
||||
val listHeaders = headers.newBuilder().apply {
|
||||
add("Accept", "application/json, text/javascript, */*; q=0.01")
|
||||
|
@ -280,7 +263,7 @@ class Aniwave : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
|
||||
return runCatching {
|
||||
val parsed = response.parseAs<ServerResponse>()
|
||||
val embedLink = utils.vrfDecrypt(DECRYPTION_KEY, parsed.result.url)
|
||||
val embedLink = utils.vrfDecrypt(KEY_DECRYPT, parsed.result.url)
|
||||
when (server.serverName) {
|
||||
"vidstream", "megaf" -> {
|
||||
vidsrcExtractor.videosFromUrl(embedLink, server.serverName, server.type)
|
||||
|
@ -325,16 +308,6 @@ class Aniwave : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun resolveSearchAnime(anime: SAnime, document: Document): Document {
|
||||
if (document.location().startsWith("$baseUrl/filter?keyword=")) { // redirected to search
|
||||
val element = document.selectFirst(searchAnimeSelector())
|
||||
val foundAnimePath = element?.selectFirst("a[href]")?.attr("href") ?: throw Exception("Search element not found (resolveSearch)")
|
||||
anime.url = foundAnimePath //probably doesn't work as intended
|
||||
return client.newCall(GET(baseUrl + foundAnimePath)).execute().asJsoup()
|
||||
}
|
||||
return document
|
||||
}
|
||||
|
||||
private fun getHosters(): Set<String> {
|
||||
val hosterSelection = preferences.getStringSet(PREF_HOSTER_KEY, PREF_HOSTER_DEFAULT)!!
|
||||
var invalidRecord = false
|
||||
|
@ -365,8 +338,6 @@ class Aniwave : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
private const val PREF_DOMAIN_KEY = "preferred_domain"
|
||||
private const val PREF_DOMAIN_DEFAULT = "https://aniwave.to"
|
||||
|
||||
private const val PREF_CUSTOM_DOMAIN_KEY = "custom_domain"
|
||||
|
||||
private const val PREF_QUALITY_KEY = "preferred_quality"
|
||||
private const val PREF_QUALITY_DEFAULT = "1080"
|
||||
|
||||
|
@ -400,25 +371,22 @@ class Aniwave : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
private val TYPES = arrayOf("Sub", "Softsub", "Dub")
|
||||
private val PREF_TYPES_TOGGLE_DEFAULT = TYPES.toSet()
|
||||
|
||||
private const val DECRYPTION_KEY = "ctpAbOz5u7S6OMkx"
|
||||
private const val ENCRYPTION_KEY = "T78s2WjTc7hSIZZR"
|
||||
// https://rowdy-avocado.github.io/multi-keys/
|
||||
private const val KEY_DECRYPT = "ctpAbOz5u7S6OMkx"
|
||||
private const val KEY_ENCRYPT = "p01EDKu734HJP1Tm"
|
||||
}
|
||||
|
||||
// ============================== Settings ==============================
|
||||
|
||||
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||
// validate hosters preferences and if invalid reset
|
||||
try {
|
||||
getHosters()
|
||||
} catch (e: Exception) {
|
||||
Log.w(name, e.toString())
|
||||
}
|
||||
|
||||
ListPreference(screen.context).apply {
|
||||
key = PREF_DOMAIN_KEY
|
||||
title = "Preferred domain"
|
||||
entries = arrayOf("aniwave.to", "aniwavetv.to (unofficial)")
|
||||
entryValues = arrayOf("https://aniwave.to", "https://aniwavetv.to")
|
||||
entries = arrayOf("aniwave.to", "aniwave.li", "aniwave.ws", "aniwave.vc")
|
||||
entryValues = arrayOf("https://aniwave.to", "https://aniwave.li", "https://aniwave.ws", "https://aniwave.vc")
|
||||
setDefaultValue(PREF_DOMAIN_DEFAULT)
|
||||
summary = "%s"
|
||||
|
||||
|
@ -514,30 +482,5 @@ class Aniwave : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||
preferences.edit().putStringSet(key, newValue as Set<String>).commit()
|
||||
}
|
||||
}.also(screen::addPreference)
|
||||
|
||||
EditTextPreference(screen.context).apply {
|
||||
key = PREF_CUSTOM_DOMAIN_KEY
|
||||
title = "Custom domain"
|
||||
setDefaultValue(null)
|
||||
val currentValue = preferences.getString(PREF_CUSTOM_DOMAIN_KEY, null)
|
||||
summary = if (currentValue.isNullOrBlank()) {
|
||||
"Custom domain of your choosing"
|
||||
} else {
|
||||
"Domain: \"$currentValue\". \nLeave blank to disable. Overrides any domain preferences!"
|
||||
}
|
||||
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
val newDomain = newValue as String
|
||||
if (newDomain.isBlank() || URLUtil.isValidUrl(newDomain)) {
|
||||
summary = "Restart to apply changes"
|
||||
Toast.makeText(screen.context, "Restart Aniyomi to apply changes", Toast.LENGTH_LONG).show()
|
||||
preferences.edit().putString(key, newDomain).apply()
|
||||
true
|
||||
} else {
|
||||
Toast.makeText(screen.context, "Invalid url. Url example: https://aniwave.to", Toast.LENGTH_LONG).show()
|
||||
false
|
||||
}
|
||||
}
|
||||
}.also(screen::addPreference)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue