Fix missing half of the page at FS. (#7989)
This commit is contained in:
		
							parent
							
								
									2262ce212d
								
							
						
					
					
						commit
						1ff4c578c3
					
				@ -1,21 +1,127 @@
 | 
			
		||||
package eu.kanade.tachiyomi.extension.en.flamescans
 | 
			
		||||
 | 
			
		||||
import android.graphics.Bitmap
 | 
			
		||||
import android.graphics.BitmapFactory
 | 
			
		||||
import android.graphics.Canvas
 | 
			
		||||
import android.graphics.Rect
 | 
			
		||||
import android.util.Log
 | 
			
		||||
import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor
 | 
			
		||||
import eu.kanade.tachiyomi.multisrc.wpmangareader.WPMangaReader
 | 
			
		||||
import eu.kanade.tachiyomi.source.model.Page
 | 
			
		||||
import okhttp3.Headers
 | 
			
		||||
import okhttp3.Interceptor
 | 
			
		||||
import okhttp3.MediaType.Companion.toMediaType
 | 
			
		||||
import okhttp3.OkHttpClient
 | 
			
		||||
import okhttp3.Protocol
 | 
			
		||||
import okhttp3.Response
 | 
			
		||||
import okhttp3.ResponseBody.Companion.toResponseBody
 | 
			
		||||
import org.jsoup.nodes.Document
 | 
			
		||||
import java.io.ByteArrayOutputStream
 | 
			
		||||
import java.util.concurrent.TimeUnit
 | 
			
		||||
 | 
			
		||||
class FlameScans : WPMangaReader("Flame Scans", "https://flamescans.org", "en", "/series") {
 | 
			
		||||
    private val rateLimitInterceptor = RateLimitInterceptor(1)
 | 
			
		||||
    private val userAgent = "Tachiyomi Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36"
 | 
			
		||||
    override fun headersBuilder(): Headers.Builder = Headers.Builder()
 | 
			
		||||
        .add("User-Agent", userAgent)
 | 
			
		||||
class FlameScans : WPMangaReader(
 | 
			
		||||
    "Flame Scans",
 | 
			
		||||
    "https://flamescans.org",
 | 
			
		||||
    "en",
 | 
			
		||||
    "/series"
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    override val client: OkHttpClient = network.cloudflareClient.newBuilder()
 | 
			
		||||
        .connectTimeout(10, TimeUnit.SECONDS)
 | 
			
		||||
        .readTimeout(30, TimeUnit.SECONDS)
 | 
			
		||||
        .addNetworkInterceptor(rateLimitInterceptor)
 | 
			
		||||
        .addInterceptor(::composedImageIntercept)
 | 
			
		||||
        .addInterceptor(RateLimitInterceptor(1, 1, TimeUnit.SECONDS))
 | 
			
		||||
        .build()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    override fun headersBuilder(): Headers.Builder = Headers.Builder()
 | 
			
		||||
        .add("User-Agent", USER_AGENT)
 | 
			
		||||
 | 
			
		||||
    private val composedSelector: String = "#readerarea div.figure_container div.composed_figure"
 | 
			
		||||
 | 
			
		||||
    override fun pageListParse(document: Document): List<Page> {
 | 
			
		||||
        val hasSplitImages = document
 | 
			
		||||
            .select(composedSelector)
 | 
			
		||||
            .firstOrNull() != null
 | 
			
		||||
 | 
			
		||||
        if (!hasSplitImages) {
 | 
			
		||||
            return super.pageListParse(document)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return document.select("#readerarea p:has(img), $composedSelector")
 | 
			
		||||
            .filter {
 | 
			
		||||
                it.select("img").all { imgEl ->
 | 
			
		||||
                    imgEl.attr("abs:src").isNullOrEmpty().not()
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            .mapIndexed { i, el ->
 | 
			
		||||
                if (el.tagName() == "p") {
 | 
			
		||||
                    Page(i, "", el.select("img").attr("abs:src"))
 | 
			
		||||
                } else {
 | 
			
		||||
                    val imageUrls = el.select("img")
 | 
			
		||||
                        .joinToString("|") { it.attr("abs:src") }
 | 
			
		||||
 | 
			
		||||
                    Page(i, "", imageUrls + COMPOSED_SUFFIX)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun composedImageIntercept(chain: Interceptor.Chain): Response {
 | 
			
		||||
        if (!chain.request().url.toString().endsWith(COMPOSED_SUFFIX)) {
 | 
			
		||||
            return chain.proceed(chain.request())
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val imageUrls = chain.request().url.toString()
 | 
			
		||||
            .removeSuffix(COMPOSED_SUFFIX)
 | 
			
		||||
            .split("%7C")
 | 
			
		||||
 | 
			
		||||
        var width = 0
 | 
			
		||||
        var height = 0
 | 
			
		||||
 | 
			
		||||
        val imageBitmaps = imageUrls.map { imageUrl ->
 | 
			
		||||
            val request = chain.request().newBuilder().url(imageUrl).build()
 | 
			
		||||
            val response = chain.proceed(request)
 | 
			
		||||
 | 
			
		||||
            val bitmap = BitmapFactory.decodeStream(response.body!!.byteStream())
 | 
			
		||||
 | 
			
		||||
            width += bitmap.width
 | 
			
		||||
            height = bitmap.height
 | 
			
		||||
 | 
			
		||||
            bitmap
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
 | 
			
		||||
        val canvas = Canvas(result)
 | 
			
		||||
 | 
			
		||||
        var left = 0
 | 
			
		||||
 | 
			
		||||
        imageBitmaps.forEach { bitmap ->
 | 
			
		||||
            val srcRect = Rect(0, 0, bitmap.width, bitmap.height)
 | 
			
		||||
            val dstRect = Rect(left, 0, left + bitmap.width, bitmap.height)
 | 
			
		||||
 | 
			
		||||
            canvas.drawBitmap(bitmap, srcRect, dstRect, null)
 | 
			
		||||
 | 
			
		||||
            left += bitmap.width
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val output = ByteArrayOutputStream()
 | 
			
		||||
        result.compress(Bitmap.CompressFormat.PNG, 100, output)
 | 
			
		||||
 | 
			
		||||
        val responseBody = output.toByteArray().toResponseBody(MEDIA_TYPE)
 | 
			
		||||
 | 
			
		||||
        return Response.Builder()
 | 
			
		||||
            .code(200)
 | 
			
		||||
            .protocol(Protocol.HTTP_1_1)
 | 
			
		||||
            .request(chain.request())
 | 
			
		||||
            .message("OK")
 | 
			
		||||
            .body(responseBody)
 | 
			
		||||
            .build()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        private const val USER_AGENT = "Tachiyomi Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
 | 
			
		||||
            "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36"
 | 
			
		||||
 | 
			
		||||
        private const val COMPOSED_SUFFIX = "?comp"
 | 
			
		||||
        private val MEDIA_TYPE = "image/png".toMediaType()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,7 @@ class WPMangaReaderGenerator : ThemeSourceGenerator {
 | 
			
		||||
        SingleLang("Mangasusu", "https://mangasusu.co.in", "id", isNsfw = true),
 | 
			
		||||
        SingleLang("TurkToon", "https://turktoon.com", "tr"),
 | 
			
		||||
        SingleLang("Gecenin Lordu", "https://geceninlordu.com/", "tr", overrideVersionCode = 1),
 | 
			
		||||
        SingleLang("Flame Scans", "https://flamescans.org", "en", overrideVersionCode = 6),
 | 
			
		||||
        SingleLang("Flame Scans", "https://flamescans.org", "en", overrideVersionCode = 7),
 | 
			
		||||
        SingleLang("A Pair of 2+", "https://pairof2.com", "en", className = "APairOf2"),
 | 
			
		||||
        SingleLang("PMScans", "https://reader.pmscans.com", "en"),
 | 
			
		||||
        SingleLang("Skull Scans", "https://www.skullscans.com", "en"),
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user