mirror of
https://github.com/gedoor/legado.git
synced 2025-08-10 00:52:30 +00:00
feat:支持更多验证方式
This commit is contained in:
@@ -67,6 +67,9 @@ java.webView(html: String?, url: String?, js: String?): String
|
||||
* @param url 要打开的链接
|
||||
* @param title 浏览器的标题
|
||||
java.startBrowser(url: String, title: String)
|
||||
|
||||
* 使用内置浏览器打开链接,并等待网页结果 .body()获取网页内容
|
||||
java.startBrowserAwait(url: String, title: String): StrResponse
|
||||
```
|
||||
* 调试
|
||||
```
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
**2022/05/04**
|
||||
|
||||
* js添加 getVerificationCode
|
||||
* js添加 getVerificationCode startBrowserAwait
|
||||
|
||||
**2022/05/02**
|
||||
|
||||
|
||||
@@ -15,13 +15,10 @@ import io.legado.app.help.http.*
|
||||
import io.legado.app.model.Debug
|
||||
import io.legado.app.model.analyzeRule.AnalyzeUrl
|
||||
import io.legado.app.model.analyzeRule.QueryTTF
|
||||
import io.legado.app.ui.association.VerificationCodeActivity
|
||||
import io.legado.app.ui.browser.WebViewActivity
|
||||
import io.legado.app.utils.*
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jsoup.Connection
|
||||
import org.jsoup.Jsoup
|
||||
import splitties.init.appCtx
|
||||
@@ -135,46 +132,28 @@ interface JsExtensions {
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用内置浏览器打开链接,可用于获取验证码 手动验证网站防爬
|
||||
* 使用内置浏览器打开链接,手动验证网站防爬
|
||||
* @param url 要打开的链接
|
||||
* @param title 浏览器页面的标题
|
||||
*/
|
||||
fun startBrowser(url: String, title: String) {
|
||||
appCtx.startActivity<WebViewActivity> {
|
||||
putExtra("title", title)
|
||||
putExtra("url", url)
|
||||
IntentData.put(url, getSource()?.getHeaderMap(true))
|
||||
}
|
||||
SourceVerificationHelp.startBrowser(getSource(), url, title)
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开验证码对话框,等待输入验证码
|
||||
* 使用内置浏览器打开链接,并等待网页结果
|
||||
*/
|
||||
fun getVerificationCode(imageUrl: String): String {
|
||||
return runBlocking {
|
||||
val key = "${getSource()?.getKey() ?: ""}_verificationCode"
|
||||
CacheManager.delete(key)
|
||||
appCtx.startActivity<VerificationCodeActivity> {
|
||||
putExtra("imageUrl", imageUrl)
|
||||
putExtra("sourceOrigin", getSource()?.getKey())
|
||||
}
|
||||
var waitUserInput: Boolean = false
|
||||
while(CacheManager.get(key) == null) {
|
||||
if (!waitUserInput) {
|
||||
log("等待输入验证码...")
|
||||
waitUserInput = true
|
||||
}
|
||||
}
|
||||
CacheManager.get(key)!!.let {
|
||||
if (it.isBlank()) {
|
||||
throw NoStackTraceException("未输入验证码或者验证码为空")
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
}
|
||||
fun startBrowserAwait(url: String, title: String): StrResponse {
|
||||
return StrResponse(url, SourceVerificationHelp.getVerificationResult(getSource(), url, title, true))
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开图片验证码对话框,等待返回验证结果
|
||||
*/
|
||||
fun getVerificationCode(imageUrl: String): String {
|
||||
return SourceVerificationHelp.getVerificationResult(getSource(), imageUrl, "", false)
|
||||
}
|
||||
|
||||
/**
|
||||
* 可从网络,本地文件(阅读私有缓存目录和书籍保存位置支持相对路径)导入JavaScript脚本
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package io.legado.app.help
|
||||
|
||||
import io.legado.app.utils.startActivity
|
||||
import io.legado.app.constant.AppLog
|
||||
import io.legado.app.exception.NoStackTraceException
|
||||
import io.legado.app.data.entities.BaseSource
|
||||
import io.legado.app.ui.browser.WebViewActivity
|
||||
import io.legado.app.ui.association.VerificationCodeActivity
|
||||
import splitties.init.appCtx
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
|
||||
object SourceVerificationHelp {
|
||||
|
||||
/**
|
||||
* 获取书源验证结果
|
||||
* 图片验证码 防爬 滑动验证码 点击字符 等等
|
||||
*/
|
||||
fun getVerificationResult(source: BaseSource?, url: String, title: String, useBrowser: Boolean): String {
|
||||
source ?: throw NoStackTraceException("getVerificationResult parameter source cannot be null")
|
||||
return runBlocking {
|
||||
val key = "${source?.getKey() ?: ""}_verificationResult"
|
||||
CacheManager.delete(key)
|
||||
|
||||
if (!useBrowser) {
|
||||
appCtx.startActivity<VerificationCodeActivity> {
|
||||
putExtra("imageUrl", url)
|
||||
putExtra("sourceOrigin", source?.getKey())
|
||||
}
|
||||
} else {
|
||||
startBrowser(source, url, title, true)
|
||||
}
|
||||
|
||||
var waitUserInput: Boolean = false
|
||||
while(CacheManager.get(key) == null) {
|
||||
if (!waitUserInput) {
|
||||
AppLog.putDebug("等待返回验证结果...")
|
||||
waitUserInput = true
|
||||
}
|
||||
}
|
||||
CacheManager.get(key)!!.let {
|
||||
if (it.isBlank()) {
|
||||
throw NoStackTraceException("验证结果为空")
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动内置浏览器
|
||||
@param saveResult 保存网页源代码到数据库
|
||||
*/
|
||||
fun startBrowser(source: BaseSource?, url: String, title: String, saveResult: Boolean? = false) {
|
||||
source ?: throw NoStackTraceException("startBrowser parameter source cannot be null")
|
||||
appCtx.startActivity<WebViewActivity> {
|
||||
putExtra("title", title)
|
||||
putExtra("url", url)
|
||||
putExtra("sourceOrigin", source?.getKey())
|
||||
putExtra("sourceVerificationEnable", saveResult)
|
||||
IntentData.put(url, source?.getHeaderMap(true))
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkActivityStatus(): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,12 @@ import io.legado.app.utils.setLayout
|
||||
import io.legado.app.utils.showDialogFragment
|
||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||
|
||||
//图片验证码输入对话框
|
||||
/**
|
||||
* 图片验证码对话框
|
||||
* 结果保存在数据库中
|
||||
* val key = "${sourceOrigin ?: ""}_verificationResult"
|
||||
* CacheManager.get(key)
|
||||
*/
|
||||
class VerificationCodeDialog() : BaseDialogFragment(R.layout.dialog_verification_code_view) {
|
||||
|
||||
constructor(imageUrl: String, sourceOrigin: String? = null) : this() {
|
||||
@@ -38,7 +43,7 @@ class VerificationCodeDialog() : BaseDialogFragment(R.layout.dialog_verification
|
||||
binding.run {
|
||||
toolBar.setBackgroundColor(primaryColor)
|
||||
val sourceOrigin = arguments?.getString("sourceOrigin")
|
||||
val key = "${sourceOrigin ?: ""}_verificationCode"
|
||||
val key = "${sourceOrigin ?: ""}_verificationResult"
|
||||
arguments?.getString("imageUrl")?.let { imageUrl ->
|
||||
ImageLoader.load(requireContext(), imageUrl).apply {
|
||||
sourceOrigin?.let {
|
||||
@@ -54,10 +59,6 @@ class VerificationCodeDialog() : BaseDialogFragment(R.layout.dialog_verification
|
||||
ivImage.setOnClickListener {
|
||||
showDialogFragment(PhotoDialog(imageUrl, sourceOrigin))
|
||||
}
|
||||
ivImage.setOnLongClickListener {
|
||||
showDialogFragment(PhotoDialog(imageUrl, sourceOrigin))
|
||||
true
|
||||
}
|
||||
}
|
||||
tvOk.setOnClickListener {
|
||||
val verificationCode = binding.verificationCode.text.toString()
|
||||
@@ -74,7 +75,7 @@ class VerificationCodeDialog() : BaseDialogFragment(R.layout.dialog_verification
|
||||
|
||||
override fun onDestroy() {
|
||||
val sourceOrigin = arguments?.getString("sourceOrigin")
|
||||
val key = "${sourceOrigin ?: ""}_verificationCode"
|
||||
val key = "${sourceOrigin ?: ""}_verificationResult"
|
||||
CacheManager.get(key) ?: CacheManager.put(key, "")
|
||||
super.onDestroy()
|
||||
activity?.finish()
|
||||
|
||||
@@ -26,6 +26,7 @@ import io.legado.app.ui.document.HandleFileContract
|
||||
import io.legado.app.utils.*
|
||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||
import java.net.URLDecoder
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
class WebViewActivity : VMBaseActivity<ActivityWebViewBinding, WebViewModel>() {
|
||||
|
||||
@@ -135,7 +136,6 @@ class WebViewActivity : VMBaseActivity<ActivityWebViewBinding, WebViewModel>() {
|
||||
viewModel.saveImage(webPic, path)
|
||||
}
|
||||
}
|
||||
|
||||
private fun selectSaveFolder() {
|
||||
val default = arrayListOf<SelectItem<Int>>()
|
||||
val path = ACache.get(this).getAsString(imagePathKey)
|
||||
@@ -176,6 +176,9 @@ class WebViewActivity : VMBaseActivity<ActivityWebViewBinding, WebViewModel>() {
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
runBlocking {
|
||||
viewModel.saveVerificationResult()
|
||||
}
|
||||
binding.webView.destroy()
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import androidx.documentfile.provider.DocumentFile
|
||||
import io.legado.app.base.BaseViewModel
|
||||
import io.legado.app.constant.AppConst
|
||||
import io.legado.app.exception.NoStackTraceException
|
||||
import io.legado.app.help.CacheManager
|
||||
import io.legado.app.help.IntentData
|
||||
import io.legado.app.help.http.newCallResponseBody
|
||||
import io.legado.app.help.http.okHttpClient
|
||||
@@ -21,6 +22,8 @@ class WebViewModel(application: Application) : BaseViewModel(application) {
|
||||
var baseUrl: String = ""
|
||||
var html: String? = null
|
||||
val headerMap: HashMap<String, String> = hashMapOf()
|
||||
var sourceVerificationEnable: Boolean = false
|
||||
var sourceOrigin: String = ""
|
||||
|
||||
fun initData(
|
||||
intent: Intent,
|
||||
@@ -29,6 +32,8 @@ class WebViewModel(application: Application) : BaseViewModel(application) {
|
||||
execute {
|
||||
val url = intent.getStringExtra("url")
|
||||
?: throw NoStackTraceException("url不能为空")
|
||||
sourceOrigin = intent.getStringExtra("sourceOrigin") ?: ""
|
||||
sourceVerificationEnable = intent.getBooleanExtra("sourceVerificationEnable", false)
|
||||
val headerMapF = IntentData.get<Map<String, String>>(url)
|
||||
val analyzeUrl = AnalyzeUrl(url, headerMapF = headerMapF)
|
||||
baseUrl = analyzeUrl.url
|
||||
@@ -78,5 +83,12 @@ class WebViewModel(application: Application) : BaseViewModel(application) {
|
||||
}
|
||||
}
|
||||
|
||||
fun saveVerificationResult() {
|
||||
if (sourceVerificationEnable) {
|
||||
val key = "${sourceOrigin}_verificationResult"
|
||||
html = AnalyzeUrl(baseUrl, headerMapF = headerMap).getStrResponse(useWebView = false).body
|
||||
CacheManager.put(key, html!!)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user