Asura Scans: support high quality chapter images (#6657)
* Asura Scans: support high quality chapter images * Only rewrite chapter images, add fallback if broken - explained in ext settings
This commit is contained in:
parent
0382073769
commit
f03fd3c5f7
|
@ -1,7 +1,7 @@
|
||||||
ext {
|
ext {
|
||||||
extName = 'Asura Scans'
|
extName = 'Asura Scans'
|
||||||
extClass = '.AsuraScans'
|
extClass = '.AsuraScans'
|
||||||
extVersionCode = 44
|
extVersionCode = 45
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "$rootDir/common.gradle"
|
apply from: "$rootDir/common.gradle"
|
||||||
|
|
|
@ -17,6 +17,8 @@ import kotlinx.serialization.decodeFromString
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
|
import okhttp3.Interceptor
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
|
@ -66,9 +68,35 @@ class AsuraScans : ParsedHttpSource(), ConfigurableSource {
|
||||||
private val json: Json by injectLazy()
|
private val json: Json by injectLazy()
|
||||||
|
|
||||||
override val client = network.cloudflareClient.newBuilder()
|
override val client = network.cloudflareClient.newBuilder()
|
||||||
|
.addInterceptor(::forceHighQualityInterceptor)
|
||||||
.rateLimit(1, 3)
|
.rateLimit(1, 3)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
|
private var failedHighQuality = false
|
||||||
|
|
||||||
|
private fun forceHighQualityInterceptor(chain: Interceptor.Chain): Response {
|
||||||
|
val request = chain.request()
|
||||||
|
|
||||||
|
if (preferences.forceHighQuality() && !failedHighQuality && request.url.fragment == "pageListParse") {
|
||||||
|
OPTIMIZED_IMAGE_PATH_REGEX.find(request.url.encodedPath)?.also { match ->
|
||||||
|
val (id, page) = match.destructured
|
||||||
|
val newUrl = request.url.newBuilder()
|
||||||
|
.encodedPath("/storage/media/$id/$page.webp")
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val response = chain.proceed(request.newBuilder().url(newUrl).build())
|
||||||
|
if (response.code != 404) {
|
||||||
|
return response
|
||||||
|
} else {
|
||||||
|
failedHighQuality = true
|
||||||
|
response.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return chain.proceed(request)
|
||||||
|
}
|
||||||
|
|
||||||
override fun headersBuilder() = super.headersBuilder()
|
override fun headersBuilder() = super.headersBuilder()
|
||||||
.add("Referer", "$baseUrl/")
|
.add("Referer", "$baseUrl/")
|
||||||
|
|
||||||
|
@ -272,7 +300,16 @@ class AsuraScans : ParsedHttpSource(), ConfigurableSource {
|
||||||
.joinToString("") { it.data().substringAfter("\"").substringBeforeLast("\"") }
|
.joinToString("") { it.data().substringAfter("\"").substringBeforeLast("\"") }
|
||||||
val pagesData = PAGES_REGEX.find(scriptData)?.groupValues?.get(1) ?: throw Exception("Failed to find chapter pages")
|
val pagesData = PAGES_REGEX.find(scriptData)?.groupValues?.get(1) ?: throw Exception("Failed to find chapter pages")
|
||||||
val pageList = json.decodeFromString<List<PageDto>>(pagesData.unescape()).sortedBy { it.order }
|
val pageList = json.decodeFromString<List<PageDto>>(pagesData.unescape()).sortedBy { it.order }
|
||||||
return pageList.mapIndexed { i, page -> Page(i, imageUrl = page.url) }
|
return pageList.mapIndexed { i, page ->
|
||||||
|
val newUrl = page.url.toHttpUrlOrNull()?.run {
|
||||||
|
newBuilder()
|
||||||
|
.fragment("pageListParse")
|
||||||
|
.build()
|
||||||
|
.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
Page(i, imageUrl = newUrl ?: page.url)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException()
|
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException()
|
||||||
|
@ -296,6 +333,16 @@ class AsuraScans : ParsedHttpSource(), ConfigurableSource {
|
||||||
summary = "Hides the chapters that require a subscription to view"
|
summary = "Hides the chapters that require a subscription to view"
|
||||||
setDefaultValue(true)
|
setDefaultValue(true)
|
||||||
}.let(screen::addPreference)
|
}.let(screen::addPreference)
|
||||||
|
|
||||||
|
SwitchPreferenceCompat(screen.context).apply {
|
||||||
|
key = PREF_FORCE_HIGH_QUALITY
|
||||||
|
title = "Force high quality chapter images"
|
||||||
|
summary = "Attempt to use high quality chapter images.\nWill increase bandwidth by ~50%."
|
||||||
|
if (failedHighQuality) {
|
||||||
|
summary = "$summary\n*DISABLED* because of missing high quality images."
|
||||||
|
}
|
||||||
|
setDefaultValue(false)
|
||||||
|
}.let(screen::addPreference)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var SharedPreferences.slugMap: MutableMap<String, String>
|
private var SharedPreferences.slugMap: MutableMap<String, String>
|
||||||
|
@ -318,6 +365,10 @@ class AsuraScans : ParsedHttpSource(), ConfigurableSource {
|
||||||
PREF_HIDE_PREMIUM_CHAPTERS,
|
PREF_HIDE_PREMIUM_CHAPTERS,
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
|
private fun SharedPreferences.forceHighQuality(): Boolean = getBoolean(
|
||||||
|
PREF_FORCE_HIGH_QUALITY,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
|
||||||
private fun String.toPermSlugIfNeeded(): String {
|
private fun String.toPermSlugIfNeeded(): String {
|
||||||
if (!preferences.dynamicUrl()) return this
|
if (!preferences.dynamicUrl()) return this
|
||||||
|
@ -337,8 +388,11 @@ class AsuraScans : ParsedHttpSource(), ConfigurableSource {
|
||||||
private val CLEAN_DATE_REGEX = """(\d+)(st|nd|rd|th)""".toRegex()
|
private val CLEAN_DATE_REGEX = """(\d+)(st|nd|rd|th)""".toRegex()
|
||||||
private val OLD_FORMAT_MANGA_REGEX = """^/manga/(\d+-)?([^/]+)/?$""".toRegex()
|
private val OLD_FORMAT_MANGA_REGEX = """^/manga/(\d+-)?([^/]+)/?$""".toRegex()
|
||||||
private val OLD_FORMAT_CHAPTER_REGEX = """^/(\d+-)?[^/]*-chapter-\d+(-\d+)*/?$""".toRegex()
|
private val OLD_FORMAT_CHAPTER_REGEX = """^/(\d+-)?[^/]*-chapter-\d+(-\d+)*/?$""".toRegex()
|
||||||
|
private val OPTIMIZED_IMAGE_PATH_REGEX = """^/storage/media/(\d+)/conversions/(.*)-optimized\.webp$""".toRegex()
|
||||||
|
|
||||||
private const val PREF_SLUG_MAP = "pref_slug_map_2"
|
private const val PREF_SLUG_MAP = "pref_slug_map_2"
|
||||||
private const val PREF_DYNAMIC_URL = "pref_dynamic_url"
|
private const val PREF_DYNAMIC_URL = "pref_dynamic_url"
|
||||||
private const val PREF_HIDE_PREMIUM_CHAPTERS = "pref_hide_premium_chapters"
|
private const val PREF_HIDE_PREMIUM_CHAPTERS = "pref_hide_premium_chapters"
|
||||||
|
private const val PREF_FORCE_HIGH_QUALITY = "pref_force_high_quality"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue