japscan didnt actually work, whoops (#4447)

* fuck sizurpp

* fix japscan completely

Co-authored-by: Rani Sargees <rani.sargees@gmail.com>
Co-authored-by: az4521 <az4521@mailinator.com>
This commit is contained in:
az4521 2020-09-27 13:45:55 -04:00 committed by GitHub
parent 910716b913
commit e96e9a627d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 45 additions and 19 deletions

View File

@ -10,7 +10,9 @@ import android.os.Handler
import android.os.Looper import android.os.Looper
import android.support.v7.preference.ListPreference import android.support.v7.preference.ListPreference
import android.support.v7.preference.PreferenceScreen import android.support.v7.preference.PreferenceScreen
import android.util.Log
import android.view.View import android.view.View
import android.webkit.JavascriptInterface
import android.webkit.WebChromeClient import android.webkit.WebChromeClient
import android.webkit.WebResourceRequest import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse import android.webkit.WebResourceResponse
@ -37,6 +39,17 @@ import java.text.ParseException
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Locale import java.util.Locale
import java.util.concurrent.CountDownLatch import java.util.concurrent.CountDownLatch
import kotlin.collections.ArrayList
import kotlin.collections.List
import kotlin.collections.distinctBy
import kotlin.collections.filter
import kotlin.collections.first
import kotlin.collections.forEach
import kotlin.collections.forEachIndexed
import kotlin.collections.map
import kotlin.collections.mapIndexed
import kotlin.collections.mutableListOf
import kotlin.collections.toTypedArray
import okhttp3.FormBody import okhttp3.FormBody
import okhttp3.MediaType import okhttp3.MediaType
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@ -65,10 +78,20 @@ class Japscan : ConfigurableSource, ParsedHttpSource() {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000) Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
} }
internal class JsObject(private val latch: CountDownLatch, var width: Int = 0, var height: Int = 0) {
@JavascriptInterface
fun passSize(widthjs: Int, ratio: Float) {
Log.d("japscan", "wvsc js returned $widthjs, $ratio")
width = widthjs
height = (width.toFloat() / ratio).toInt()
latch.countDown()
}
}
@SuppressLint("SetJavaScriptEnabled") @SuppressLint("SetJavaScriptEnabled")
override val client: OkHttpClient = network.cloudflareClient.newBuilder().addInterceptor { chain -> override val client: OkHttpClient = network.cloudflareClient.newBuilder().addInterceptor { chain ->
val indicator = "&wvsc" val indicator = "&wvsc"
val cleanupjs = "var db=document.body,chl=db.children;for(db.appendChild(document.getElementsByTagName('CNV-VV')[0]);'CNV-VV'!=chl[0].tagName;)db.removeChild(chl[0]);for(var i of[].slice.call(chl[0].all_canvas)){i.style.maxWidth=(i.width+\"px\")}window.variable={w:chl[0].all_canvas[0].width,h:chl[0].all_canvas[0].height};" val cleanupjs = "var checkExist=setInterval(function(){if(document.getElementsByTagName('CNV-VV').length){clearInterval(checkExist);var e=document.body,a=e.children;for(e.appendChild(document.getElementsByTagName('CNV-VV')[0]);'CNV-VV'!=a[0].tagName;)e.removeChild(a[0]);for(var t of[].slice.call(a[0].all_canvas))t.style.maxWidth='100%';window.android.passSize(a[0].all_canvas[0].width,a[0].all_canvas[0].width/a[0].all_canvas[0].height)}},100);"
val request = chain.request() val request = chain.request()
val url = request.url().toString() val url = request.url().toString()
@ -83,28 +106,25 @@ class Japscan : ConfigurableSource, ParsedHttpSource() {
var webView: WebView? = null var webView: WebView? = null
var height = 0 var height = 0
var width = 0 var width = 0
val jsinterface = JsObject(latch)
Log.d("japscan", "init wvsc")
handler.post { handler.post {
val webview = WebView(Injekt.get<Application>()) val webview = WebView(Injekt.get<Application>())
webView = webview webView = webview
webview.settings.javaScriptEnabled = true webview.settings.javaScriptEnabled = true
webview.settings.domStorageEnabled = true webview.settings.domStorageEnabled = true
webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null) webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
webview.settings.useWideViewPort = false
webview.settings.loadWithOverviewMode = false
webview.settings.userAgentString = webview.settings.userAgentString.replace("Mobile", "eliboM").replace("Android", "diordnA")
webview.addJavascriptInterface(jsinterface, "android")
var retries = 1
webview.webChromeClient = object : WebChromeClient() { webview.webChromeClient = object : WebChromeClient() {
@SuppressLint("NewApi") @SuppressLint("NewApi")
override fun onProgressChanged(view: WebView, progress: Int) { override fun onProgressChanged(view: WebView, progress: Int) {
if (progress == 100) { if (progress == 100 && retries--> 0) {
view.evaluateJavascript(cleanupjs) { Log.d("japscan", "wvsc loading finished")
if (it.contains('{')) { view.evaluateJavascript(cleanupjs) {}
val j = JsonParser().parse(it).asJsonObject
width = j["w"].asInt
height = j["h"].asInt
latch.countDown()
} else {
webview.loadUrl(url.replace("&wvsc", ""))
}
}
} }
} }
} }
@ -112,11 +132,12 @@ class Japscan : ConfigurableSource, ParsedHttpSource() {
} }
latch.await() latch.await()
width = jsinterface.width
height = jsinterface.height
// webView!!.isDrawingCacheEnabled = true // webView!!.isDrawingCacheEnabled = true
webView!!.measure(width + 100, height + 100) webView!!.measure(width, height)
webView!!.layout(0, 0, width + 100, height + 100) webView!!.layout(0, 0, width, height)
Thread.sleep(350) Thread.sleep(350)
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
@ -126,8 +147,8 @@ class Japscan : ConfigurableSource, ParsedHttpSource() {
// val bitmap: Bitmap = webView!!.drawingCache // val bitmap: Bitmap = webView!!.drawingCache
val output = ByteArrayOutputStream() val output = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.PNG, 100, output) bitmap.compress(Bitmap.CompressFormat.PNG, 100, output)
val rb = ResponseBody.create(MediaType.parse("image/png"), output.toByteArray()) val rb = ResponseBody.create(MediaType.parse("image/png"), output.toByteArray())
handler.post { webView!!.destroy() }
response.newBuilder().body(rb).build() response.newBuilder().body(rb).build()
}.build() }.build()
@ -312,13 +333,16 @@ class Japscan : ConfigurableSource, ParsedHttpSource() {
} }
override fun pageListParse(document: Document): List<Page> { override fun pageListParse(document: Document): List<Page> {
return if (document.getElementsByTag("script").size> 12) { // scrambled images, webview screenshotting return if (document.getElementsByTag("script").filter { it.attr("src").contains("ujs") }.size > 2) { // scrambled images, webview screenshotting
Log.d("japscan", "scrambled, loading in WVSC urls")
document.getElementsByTag("option").mapIndexed { i, it -> Page(i, "", baseUrl + it.attr("value") + "&wvsc") } document.getElementsByTag("option").mapIndexed { i, it -> Page(i, "", baseUrl + it.attr("value") + "&wvsc") }
} else { } else {
// unscrambled images, check for single page // unscrambled images, check for single page
val zjsurl = document.getElementsByTag("script").first { it.attr("src").contains("zjs", ignoreCase = true) }.attr("src") val zjsurl = document.getElementsByTag("script").first { it.attr("src").contains("zjs", ignoreCase = true) }.attr("src")
Log.d("japscan", "ZJS at $zjsurl")
val zjs = client.newCall(GET(baseUrl + zjsurl, headers)).execute().body()!!.string() val zjs = client.newCall(GET(baseUrl + zjsurl, headers)).execute().body()!!.string()
if ((zjs.toLowerCase().split("new image").size - 1) == 1) { // single page, webview request dumping if ((zjs.toLowerCase().split("new image").size - 1) == 1) { // single page, webview request dumping
Log.d("japscan", "webtoon, netdumping initiated")
val pagecount = document.getElementsByTag("option").size val pagecount = document.getElementsByTag("option").size
val pages = ArrayList<Page>() val pages = ArrayList<Page>()
val handler = Handler(Looper.getMainLooper()) val handler = Handler(Looper.getMainLooper())
@ -339,6 +363,7 @@ class Japscan : ConfigurableSource, ParsedHttpSource() {
): WebResourceResponse? { ): WebResourceResponse? {
if (request.url.toString().startsWith("https://c.")) { if (request.url.toString().startsWith("https://c.")) {
pages.add(Page(pages.size, "", request.url.toString())) pages.add(Page(pages.size, "", request.url.toString()))
Log.d("japscan", "intercepted ${request.url}")
if (pages.size == pagecount) { latch.countDown() } if (pages.size == pagecount) { latch.countDown() }
return WebResourceResponse("image/jpeg", "UTF-8", ByteArrayInputStream(dummystream.toByteArray())) return WebResourceResponse("image/jpeg", "UTF-8", ByteArrayInputStream(dummystream.toByteArray()))
} }
@ -350,6 +375,7 @@ class Japscan : ConfigurableSource, ParsedHttpSource() {
latch.await() latch.await()
return pages return pages
} else { // page by page, just do webview screenshotting because it's easier } else { // page by page, just do webview screenshotting because it's easier
Log.d("japscan", "unscrambled, loading WVSC urls")
document.getElementsByTag("option").mapIndexed { i, it -> Page(i, "", baseUrl + it.attr("value") + "&wvsc") } document.getElementsByTag("option").mapIndexed { i, it -> Page(i, "", baseUrl + it.attr("value") + "&wvsc") }
} }
} }