@@ -17,6 +17,8 @@ import kotlinx.serialization.decodeFromString
17
17
import kotlinx.serialization.encodeToString
18
18
import kotlinx.serialization.json.Json
19
19
import okhttp3.HttpUrl.Companion.toHttpUrl
20
+ import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
21
+ import okhttp3.Interceptor
20
22
import okhttp3.Request
21
23
import okhttp3.Response
22
24
import org.jsoup.nodes.Document
@@ -66,9 +68,35 @@ class AsuraScans : ParsedHttpSource(), ConfigurableSource {
66
68
private val json: Json by injectLazy()
67
69
68
70
override val client = network.cloudflareClient.newBuilder()
71
+ .addInterceptor(::forceHighQualityInterceptor)
69
72
.rateLimit(1 , 3 )
70
73
.build()
71
74
75
+ private var failedHighQuality = false
76
+
77
+ private fun forceHighQualityInterceptor (chain : Interceptor .Chain ): Response {
78
+ val request = chain.request()
79
+
80
+ if (preferences.forceHighQuality() && ! failedHighQuality && request.url.fragment == " pageListParse" ) {
81
+ OPTIMIZED_IMAGE_PATH_REGEX .find(request.url.encodedPath)?.also { match ->
82
+ val (id, page) = match.destructured
83
+ val newUrl = request.url.newBuilder()
84
+ .encodedPath(" /storage/media/$id /$page .webp" )
85
+ .build()
86
+
87
+ val response = chain.proceed(request.newBuilder().url(newUrl).build())
88
+ if (response.code != 404 ) {
89
+ return response
90
+ } else {
91
+ failedHighQuality = true
92
+ response.close()
93
+ }
94
+ }
95
+ }
96
+
97
+ return chain.proceed(request)
98
+ }
99
+
72
100
override fun headersBuilder () = super .headersBuilder()
73
101
.add(" Referer" , " $baseUrl /" )
74
102
@@ -272,7 +300,16 @@ class AsuraScans : ParsedHttpSource(), ConfigurableSource {
272
300
.joinToString(" " ) { it.data().substringAfter(" \" " ).substringBeforeLast(" \" " ) }
273
301
val pagesData = PAGES_REGEX .find(scriptData)?.groupValues?.get(1 ) ? : throw Exception (" Failed to find chapter pages" )
274
302
val pageList = json.decodeFromString<List <PageDto >>(pagesData.unescape()).sortedBy { it.order }
275
- return pageList.mapIndexed { i, page -> Page (i, imageUrl = page.url) }
303
+ return pageList.mapIndexed { i, page ->
304
+ val newUrl = page.url.toHttpUrlOrNull()?.run {
305
+ newBuilder()
306
+ .fragment(" pageListParse" )
307
+ .build()
308
+ .toString()
309
+ }
310
+
311
+ Page (i, imageUrl = newUrl ? : page.url)
312
+ }
276
313
}
277
314
278
315
override fun imageUrlParse (document : Document ) = throw UnsupportedOperationException ()
@@ -296,6 +333,16 @@ class AsuraScans : ParsedHttpSource(), ConfigurableSource {
296
333
summary = " Hides the chapters that require a subscription to view"
297
334
setDefaultValue(true )
298
335
}.let (screen::addPreference)
336
+
337
+ SwitchPreferenceCompat (screen.context).apply {
338
+ key = PREF_FORCE_HIGH_QUALITY
339
+ title = " Force high quality chapter images"
340
+ summary = " Attempt to use high quality chapter images.\n Will increase bandwidth by ~50%."
341
+ if (failedHighQuality) {
342
+ summary = " $summary \n *DISABLED* because of missing high quality images."
343
+ }
344
+ setDefaultValue(false )
345
+ }.let (screen::addPreference)
299
346
}
300
347
301
348
private var SharedPreferences .slugMap: MutableMap <String , String >
@@ -318,6 +365,10 @@ class AsuraScans : ParsedHttpSource(), ConfigurableSource {
318
365
PREF_HIDE_PREMIUM_CHAPTERS ,
319
366
true ,
320
367
)
368
+ private fun SharedPreferences.forceHighQuality (): Boolean = getBoolean(
369
+ PREF_FORCE_HIGH_QUALITY ,
370
+ false ,
371
+ )
321
372
322
373
private fun String.toPermSlugIfNeeded (): String {
323
374
if (! preferences.dynamicUrl()) return this
@@ -337,8 +388,11 @@ class AsuraScans : ParsedHttpSource(), ConfigurableSource {
337
388
private val CLEAN_DATE_REGEX = """ (\d+)(st|nd|rd|th)""" .toRegex()
338
389
private val OLD_FORMAT_MANGA_REGEX = """ ^/manga/(\d+-)?([^/]+)/?$""" .toRegex()
339
390
private val OLD_FORMAT_CHAPTER_REGEX = """ ^/(\d+-)?[^/]*-chapter-\d+(-\d+)*/?$""" .toRegex()
391
+ private val OPTIMIZED_IMAGE_PATH_REGEX = """ ^/storage/media/(\d+)/conversions/(.*)-optimized\.webp$""" .toRegex()
392
+
340
393
private const val PREF_SLUG_MAP = " pref_slug_map_2"
341
394
private const val PREF_DYNAMIC_URL = " pref_dynamic_url"
342
395
private const val PREF_HIDE_PREMIUM_CHAPTERS = " pref_hide_premium_chapters"
396
+ private const val PREF_FORCE_HIGH_QUALITY = " pref_force_high_quality"
343
397
}
344
398
}
0 commit comments