Baozimanhua: fix page list parse (#12064)
* Baozimanhua: fix page list parse * Baozimanhua: make interceptor singleton * Baozimanhua: remove some overhead in interceptor
This commit is contained in:
		
							parent
							
								
									05b75dd216
								
							
						
					
					
						commit
						42e6a5064f
					
				| @ -1,3 +1,8 @@ | |||||||
|  | ## 1.2.7 (2022-06-04) | ||||||
|  | 
 | ||||||
|  | - 修复章节图片解析 | ||||||
|  | - 整理筛选器代码 | ||||||
|  | 
 | ||||||
| ## 1.2.6 (2022-05-27) | ## 1.2.6 (2022-05-27) | ||||||
| 
 | 
 | ||||||
| - 整理代码 | - 整理代码 | ||||||
|  | |||||||
| @ -5,7 +5,7 @@ ext { | |||||||
|     extName = 'Baozimanhua' |     extName = 'Baozimanhua' | ||||||
|     pkgNameSuffix = 'zh.baozimanhua' |     pkgNameSuffix = 'zh.baozimanhua' | ||||||
|     extClass = '.Baozimanhua' |     extClass = '.Baozimanhua' | ||||||
|     extVersionCode = 6 |     extVersionCode = 7 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| apply from: "$rootDir/common.gradle" | apply from: "$rootDir/common.gradle" | ||||||
|  | |||||||
| @ -9,7 +9,11 @@ package eu.kanade.tachiyomi.extension.zh.baozimanhua | |||||||
| const val BANNER_BASE64 = "\ | const val BANNER_BASE64 = "\ | ||||||
| ''' | ''' | ||||||
| 
 | 
 | ||||||
| tail = b'"\n' | tail = b'''\ | ||||||
|  | " | ||||||
|  | const val BANNER_WIDTH = 800 | ||||||
|  | const val BANNER_HEIGHT = 282 | ||||||
|  | ''' | ||||||
| 
 | 
 | ||||||
| with open('src/eu/kanade/tachiyomi/extension/zh/baozimanhua/BannerData.kt', 'wb') as f: | with open('src/eu/kanade/tachiyomi/extension/zh/baozimanhua/BannerData.kt', 'wb') as f: | ||||||
|     f.write(head) |     f.write(head) | ||||||
|  | |||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -8,24 +8,20 @@ import okhttp3.MediaType.Companion.toMediaType | |||||||
| import okhttp3.Response | import okhttp3.Response | ||||||
| import okhttp3.ResponseBody.Companion.toResponseBody | import okhttp3.ResponseBody.Companion.toResponseBody | ||||||
| import java.io.ByteArrayOutputStream | import java.io.ByteArrayOutputStream | ||||||
| import java.util.EnumSet |  | ||||||
| import kotlin.math.abs | import kotlin.math.abs | ||||||
| 
 | 
 | ||||||
| class BannerInterceptor : Interceptor { | object BannerInterceptor : Interceptor { | ||||||
|     private val banner: Bitmap by lazy { |     private const val w = BANNER_WIDTH | ||||||
|         val buffer = Base64.decode(BANNER_BASE64, Base64.DEFAULT) |     private const val h = BANNER_HEIGHT | ||||||
|         BitmapFactory.decodeByteArray(buffer, 0, buffer.size) |     private const val size = w * h | ||||||
|     } |     private const val threshold = w * h * 3 // 1 per pixel per channel | ||||||
|     private val w by lazy { banner.width } |  | ||||||
|     private val h by lazy { banner.height } |  | ||||||
|     private val size by lazy { w * h } |  | ||||||
|     private val bannerBuffer by lazy { |     private val bannerBuffer by lazy { | ||||||
|         val buffer = IntArray(size) |         val buffer = Base64.decode(BANNER_BASE64, Base64.DEFAULT) | ||||||
|         banner.getPixels(buffer, 0, w, 0, 0, w, h) |         val banner = BitmapFactory.decodeByteArray(buffer, 0, buffer.size) | ||||||
|         banner.recycle() |         val pixels = IntArray(size) | ||||||
|         buffer |         banner.getPixels(pixels, 0, w, 0, 0, w, h) | ||||||
|  |         pixels | ||||||
|     } |     } | ||||||
|     private val threshold by lazy { w * h * 3 } // 1 per pixel per channel |  | ||||||
| 
 | 
 | ||||||
|     override fun intercept(chain: Interceptor.Chain): Response { |     override fun intercept(chain: Interceptor.Chain): Response { | ||||||
|         val url = chain.request().url.toString() |         val url = chain.request().url.toString() | ||||||
| @ -36,12 +32,12 @@ class BannerInterceptor : Interceptor { | |||||||
|         val content = body.bytes() |         val content = body.bytes() | ||||||
|         val bitmap = BitmapFactory.decodeByteArray(content, 0, content.size) |         val bitmap = BitmapFactory.decodeByteArray(content, 0, content.size) | ||||||
|         val positions = checkBanner(bitmap) |         val positions = checkBanner(bitmap) | ||||||
|         return if (positions.isEmpty()) { |         return if (positions == 0) { | ||||||
|             response.newBuilder().body(content.toResponseBody(contentType)).build() |             response.newBuilder().body(content.toResponseBody(contentType)).build() | ||||||
|         } else { |         } else { | ||||||
|             val result = Bitmap.createBitmap( |             val result = Bitmap.createBitmap( | ||||||
|                 bitmap, 0, if (positions.contains(BannerPosition.TOP)) h else 0, |                 bitmap, 0, if (positions and TOP == TOP) h else 0, | ||||||
|                 bitmap.width, bitmap.height - h * positions.size |                 bitmap.width, bitmap.height - if (positions == BOTH) h * 2 else h | ||||||
|             ) |             ) | ||||||
|             val output = ByteArrayOutputStream() |             val output = ByteArrayOutputStream() | ||||||
|             result.compress(Bitmap.CompressFormat.JPEG, 90, output) |             result.compress(Bitmap.CompressFormat.JPEG, 90, output) | ||||||
| @ -50,16 +46,16 @@ class BannerInterceptor : Interceptor { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private fun checkBanner(image: Bitmap): EnumSet<BannerPosition> { |     private fun checkBanner(image: Bitmap): Int { | ||||||
|         val result = EnumSet.noneOf(BannerPosition::class.java) |         if (image.width < w || image.height < h) return 0 | ||||||
|         if (image.width < w || image.height < h) return result |         if ((image.width - w) % 2 != 0) return 0 | ||||||
|         if ((image.width - w) % 2 != 0) return result |  | ||||||
|         val pad = (image.width - w) / 2 |         val pad = (image.width - w) / 2 | ||||||
|         val buf = IntArray(size) |         val buf = IntArray(size) | ||||||
|  |         var result = 0 | ||||||
|         image.getPixels(buf, 0, w, pad, 0, w, h) // top |         image.getPixels(buf, 0, w, pad, 0, w, h) // top | ||||||
|         if (isIdentical(bannerBuffer, buf)) result.add(BannerPosition.TOP) |         if (isIdentical(bannerBuffer, buf)) result = result or TOP | ||||||
|         image.getPixels(buf, 0, w, pad, image.height - h, w, h) // bottom |         image.getPixels(buf, 0, w, pad, image.height - h, w, h) // bottom | ||||||
|         if (isIdentical(bannerBuffer, buf)) result.add(BannerPosition.BOTTOM) |         if (isIdentical(bannerBuffer, buf)) result = result or BOTTOM | ||||||
|         return result |         return result | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -76,7 +72,9 @@ class BannerInterceptor : Interceptor { | |||||||
|         return true |         return true | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private enum class BannerPosition { TOP, BOTTOM } |     private const val TOP = 0b01 | ||||||
| } |     private const val BOTTOM = 0b10 | ||||||
|  |     private const val BOTH = 0b11 | ||||||
| 
 | 
 | ||||||
|     const val COMIC_IMAGE_SUFFIX = "#baozi" |     const val COMIC_IMAGE_SUFFIX = "#baozi" | ||||||
|  | } | ||||||
|  | |||||||
| @ -40,7 +40,7 @@ class Baozimanhua : ParsedHttpSource(), ConfigurableSource { | |||||||
|     override val supportsLatest = true |     override val supportsLatest = true | ||||||
| 
 | 
 | ||||||
|     override val client: OkHttpClient = network.cloudflareClient.newBuilder() |     override val client: OkHttpClient = network.cloudflareClient.newBuilder() | ||||||
|         .addInterceptor(BannerInterceptor()).build() |         .addInterceptor(BannerInterceptor).build() | ||||||
| 
 | 
 | ||||||
|     override fun chapterListSelector() = throw UnsupportedOperationException("Not used.") |     override fun chapterListSelector() = throw UnsupportedOperationException("Not used.") | ||||||
| 
 | 
 | ||||||
| @ -108,8 +108,8 @@ class Baozimanhua : ParsedHttpSource(), ConfigurableSource { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     override fun pageListParse(document: Document): List<Page> { |     override fun pageListParse(document: Document): List<Page> { | ||||||
|         return document.select(".comic-contain > .chapter-img > img").mapIndexed { index, element -> |         return document.select(".comic-contain > amp-img").mapIndexed { index, element -> | ||||||
|             Page(index, imageUrl = element.attr("data-src").trim() + COMIC_IMAGE_SUFFIX) |             Page(index, imageUrl = element.attr("src").trim() + BannerInterceptor.COMIC_IMAGE_SUFFIX) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -145,27 +145,8 @@ class Baozimanhua : ParsedHttpSource(), ConfigurableSource { | |||||||
|         return if (query.isNotEmpty()) { |         return if (query.isNotEmpty()) { | ||||||
|             GET("$baseUrl/search?q=$query", headers) |             GET("$baseUrl/search?q=$query", headers) | ||||||
|         } else { |         } else { | ||||||
|             lateinit var tag: String |             val parts = filters.filterIsInstance<UriPartFilter>().joinToString("&") { it.toUriPart() } | ||||||
|             lateinit var region: String |             GET("$baseUrl/classify?page=$page&$parts", headers) | ||||||
|             lateinit var status: String |  | ||||||
|             lateinit var start: String |  | ||||||
|             filters.forEach { filter -> |  | ||||||
|                 when (filter) { |  | ||||||
|                     is TagFilter -> { |  | ||||||
|                         tag = filter.toUriPart() |  | ||||||
|                     } |  | ||||||
|                     is RegionFilter -> { |  | ||||||
|                         region = filter.toUriPart() |  | ||||||
|                     } |  | ||||||
|                     is StatusFilter -> { |  | ||||||
|                         status = filter.toUriPart() |  | ||||||
|                     } |  | ||||||
|                     is StartFilter -> { |  | ||||||
|                         start = filter.toUriPart() |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             GET("$baseUrl/classify?type=$tag®ion=$region&state=$status&filter=$start&page=$page") |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -194,13 +175,14 @@ class Baozimanhua : ParsedHttpSource(), ConfigurableSource { | |||||||
|         StartFilter() |         StartFilter() | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     private open class UriPartFilter(displayName: String, val vals: Array<Pair<String, String>>) : |     private open class UriPartFilter(name: String, val query: String, val vals: Array<Pair<String, String>>) : | ||||||
|         Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) { |         Filter.Select<String>(name, vals.map { it.first }.toTypedArray()) { | ||||||
|         fun toUriPart() = vals[state].second |         fun toUriPart() = "$query=${vals[state].second}" | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private class TagFilter : UriPartFilter( |     private class TagFilter : UriPartFilter( | ||||||
|         "标签", |         "标签", | ||||||
|  |         "type", | ||||||
|         arrayOf( |         arrayOf( | ||||||
|             Pair("全部", "all"), |             Pair("全部", "all"), | ||||||
|             Pair("都市", "dushi"), |             Pair("都市", "dushi"), | ||||||
| @ -271,6 +253,7 @@ class Baozimanhua : ParsedHttpSource(), ConfigurableSource { | |||||||
| 
 | 
 | ||||||
|     private class RegionFilter : UriPartFilter( |     private class RegionFilter : UriPartFilter( | ||||||
|         "地区", |         "地区", | ||||||
|  |         "region", | ||||||
|         arrayOf( |         arrayOf( | ||||||
|             Pair("全部", "all"), |             Pair("全部", "all"), | ||||||
|             Pair("国漫", "cn"), |             Pair("国漫", "cn"), | ||||||
| @ -282,6 +265,7 @@ class Baozimanhua : ParsedHttpSource(), ConfigurableSource { | |||||||
| 
 | 
 | ||||||
|     private class StatusFilter : UriPartFilter( |     private class StatusFilter : UriPartFilter( | ||||||
|         "进度", |         "进度", | ||||||
|  |         "state", | ||||||
|         arrayOf( |         arrayOf( | ||||||
|             Pair("全部", "all"), |             Pair("全部", "all"), | ||||||
|             Pair("连载中", "serial"), |             Pair("连载中", "serial"), | ||||||
| @ -291,6 +275,7 @@ class Baozimanhua : ParsedHttpSource(), ConfigurableSource { | |||||||
| 
 | 
 | ||||||
|     private class StartFilter : UriPartFilter( |     private class StartFilter : UriPartFilter( | ||||||
|         "标题开头", |         "标题开头", | ||||||
|  |         "filter", | ||||||
|         arrayOf( |         arrayOf( | ||||||
|             Pair("全部", "*"), |             Pair("全部", "*"), | ||||||
|             Pair("ABCD", "ABCD"), |             Pair("ABCD", "ABCD"), | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 kasperskier
						kasperskier