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 { | ||||
|     extName = 'Asura Scans' | ||||
|     extClass = '.AsuraScans' | ||||
|     extVersionCode = 44 | ||||
|     extVersionCode = 45 | ||||
| } | ||||
| 
 | ||||
| apply from: "$rootDir/common.gradle" | ||||
|  | ||||
| @ -17,6 +17,8 @@ import kotlinx.serialization.decodeFromString | ||||
| import kotlinx.serialization.encodeToString | ||||
| import kotlinx.serialization.json.Json | ||||
| import okhttp3.HttpUrl.Companion.toHttpUrl | ||||
| import okhttp3.HttpUrl.Companion.toHttpUrlOrNull | ||||
| import okhttp3.Interceptor | ||||
| import okhttp3.Request | ||||
| import okhttp3.Response | ||||
| import org.jsoup.nodes.Document | ||||
| @ -66,9 +68,35 @@ class AsuraScans : ParsedHttpSource(), ConfigurableSource { | ||||
|     private val json: Json by injectLazy() | ||||
| 
 | ||||
|     override val client = network.cloudflareClient.newBuilder() | ||||
|         .addInterceptor(::forceHighQualityInterceptor) | ||||
|         .rateLimit(1, 3) | ||||
|         .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() | ||||
|         .add("Referer", "$baseUrl/") | ||||
| 
 | ||||
| @ -272,7 +300,16 @@ class AsuraScans : ParsedHttpSource(), ConfigurableSource { | ||||
|             .joinToString("") { it.data().substringAfter("\"").substringBeforeLast("\"") } | ||||
|         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 } | ||||
|         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() | ||||
| @ -296,6 +333,16 @@ class AsuraScans : ParsedHttpSource(), ConfigurableSource { | ||||
|             summary = "Hides the chapters that require a subscription to view" | ||||
|             setDefaultValue(true) | ||||
|         }.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> | ||||
| @ -318,6 +365,10 @@ class AsuraScans : ParsedHttpSource(), ConfigurableSource { | ||||
|         PREF_HIDE_PREMIUM_CHAPTERS, | ||||
|         true, | ||||
|     ) | ||||
|     private fun SharedPreferences.forceHighQuality(): Boolean = getBoolean( | ||||
|         PREF_FORCE_HIGH_QUALITY, | ||||
|         false, | ||||
|     ) | ||||
| 
 | ||||
|     private fun String.toPermSlugIfNeeded(): String { | ||||
|         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 OLD_FORMAT_MANGA_REGEX = """^/manga/(\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_DYNAMIC_URL = "pref_dynamic_url" | ||||
|         private const val PREF_HIDE_PREMIUM_CHAPTERS = "pref_hide_premium_chapters" | ||||
|         private const val PREF_FORCE_HIGH_QUALITY = "pref_force_high_quality" | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Vetle Ledaal
						Vetle Ledaal