Fix Cloudflare protection resolving
This commit is contained in:
@@ -19,7 +19,7 @@ android {
|
||||
applicationId 'org.koitharu.kotatsu'
|
||||
minSdk = 21
|
||||
targetSdk = 35
|
||||
versionCode = 1006
|
||||
versionCode = 1007
|
||||
versionName = '8.1.1'
|
||||
generatedDensities = []
|
||||
testInstrumentationRunner 'org.koitharu.kotatsu.HiltTestRunner'
|
||||
|
||||
@@ -6,10 +6,18 @@ import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updatePadding
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.core.nav.AppRouter
|
||||
import org.koitharu.kotatsu.core.network.CommonHeaders
|
||||
import org.koitharu.kotatsu.core.network.proxy.ProxyProvider
|
||||
import org.koitharu.kotatsu.core.parser.MangaRepository
|
||||
import org.koitharu.kotatsu.core.parser.ParserMangaRepository
|
||||
import org.koitharu.kotatsu.core.ui.BaseActivity
|
||||
import org.koitharu.kotatsu.core.util.ext.configureForParser
|
||||
import org.koitharu.kotatsu.core.util.ext.consumeAll
|
||||
import org.koitharu.kotatsu.databinding.ActivityBrowserBinding
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.util.nullIfEmpty
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
@@ -18,6 +26,9 @@ abstract class BaseBrowserActivity : BaseActivity<ActivityBrowserBinding>(), Bro
|
||||
@Inject
|
||||
lateinit var proxyProvider: ProxyProvider
|
||||
|
||||
@Inject
|
||||
lateinit var mangaRepositoryFactory: MangaRepository.Factory
|
||||
|
||||
private lateinit var onBackPressedCallback: WebViewBackPressedCallback
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -28,10 +39,21 @@ abstract class BaseBrowserActivity : BaseActivity<ActivityBrowserBinding>(), Bro
|
||||
viewBinding.webView.webChromeClient = ProgressChromeClient(viewBinding.progressBar)
|
||||
onBackPressedCallback = WebViewBackPressedCallback(viewBinding.webView)
|
||||
onBackPressedDispatcher.addCallback(onBackPressedCallback)
|
||||
onCreate2(savedInstanceState)
|
||||
|
||||
val mangaSource = MangaSource(intent?.getStringExtra(AppRouter.KEY_SOURCE))
|
||||
val repository = mangaRepositoryFactory.create(mangaSource) as? ParserMangaRepository
|
||||
val userAgent = intent?.getStringExtra(AppRouter.KEY_USER_AGENT)?.nullIfEmpty()
|
||||
?: repository?.getRequestHeaders()?.get(CommonHeaders.USER_AGENT)
|
||||
viewBinding.webView.configureForParser(userAgent)
|
||||
|
||||
onCreate2(savedInstanceState, mangaSource, repository)
|
||||
}
|
||||
|
||||
protected abstract fun onCreate2(savedInstanceState: Bundle?)
|
||||
protected abstract fun onCreate2(
|
||||
savedInstanceState: Bundle?,
|
||||
source: MangaSource,
|
||||
repository: ParserMangaRepository?
|
||||
)
|
||||
|
||||
override fun onApplyWindowInsets(
|
||||
v: View,
|
||||
|
||||
@@ -8,30 +8,19 @@ import com.google.android.material.snackbar.Snackbar
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.core.nav.AppRouter
|
||||
import org.koitharu.kotatsu.core.nav.router
|
||||
import org.koitharu.kotatsu.core.network.CommonHeaders
|
||||
import org.koitharu.kotatsu.core.parser.MangaRepository
|
||||
import org.koitharu.kotatsu.core.parser.ParserMangaRepository
|
||||
import org.koitharu.kotatsu.core.util.ext.configureForParser
|
||||
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
|
||||
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
|
||||
import javax.inject.Inject
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
|
||||
@AndroidEntryPoint
|
||||
class BrowserActivity : BaseBrowserActivity() {
|
||||
|
||||
@Inject
|
||||
lateinit var mangaRepositoryFactory: MangaRepository.Factory
|
||||
|
||||
override fun onCreate2(savedInstanceState: Bundle?) {
|
||||
setDisplayHomeAsUp(true, true)
|
||||
val mangaSource = MangaSource(intent?.getStringExtra(AppRouter.KEY_SOURCE))
|
||||
val repository = mangaRepositoryFactory.create(mangaSource) as? ParserMangaRepository
|
||||
val userAgent = repository?.getRequestHeaders()?.get(CommonHeaders.USER_AGENT)
|
||||
viewBinding.webView.configureForParser(userAgent)
|
||||
viewBinding.webView.webViewClient = BrowserClient(proxyProvider, this)
|
||||
override fun onCreate2(savedInstanceState: Bundle?, source: MangaSource, repository: ParserMangaRepository?) {
|
||||
setDisplayHomeAsUp(isEnabled = true, showUpAsClose = true)
|
||||
viewBinding.webView.webViewClient = BrowserClient(this)
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
proxyProvider.applyWebViewConfig()
|
||||
|
||||
@@ -3,10 +3,8 @@ package org.koitharu.kotatsu.browser
|
||||
import android.graphics.Bitmap
|
||||
import android.webkit.WebView
|
||||
import androidx.webkit.WebViewClientCompat
|
||||
import org.koitharu.kotatsu.core.network.proxy.ProxyProvider
|
||||
|
||||
open class BrowserClient(
|
||||
private val proxyProvider: ProxyProvider,
|
||||
private val callback: BrowserCallback
|
||||
) : WebViewClientCompat() {
|
||||
|
||||
|
||||
@@ -22,9 +22,11 @@ import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.core.nav.AppRouter
|
||||
import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar
|
||||
import org.koitharu.kotatsu.core.util.ext.configureForParser
|
||||
import org.koitharu.kotatsu.core.parser.ParserMangaRepository
|
||||
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.network.CloudFlareHelper
|
||||
import org.koitharu.kotatsu.parsers.util.ifNullOrEmpty
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
@@ -37,15 +39,14 @@ class CloudFlareActivity : BaseBrowserActivity(), CloudFlareCallback {
|
||||
|
||||
private lateinit var cfClient: CloudFlareClient
|
||||
|
||||
override fun onCreate2(savedInstanceState: Bundle?) {
|
||||
setDisplayHomeAsUp(true, true)
|
||||
override fun onCreate2(savedInstanceState: Bundle?, source: MangaSource, repository: ParserMangaRepository?) {
|
||||
setDisplayHomeAsUp(isEnabled = true, showUpAsClose = true)
|
||||
val url = intent?.dataString
|
||||
if (url.isNullOrEmpty()) {
|
||||
finishAfterTransition()
|
||||
return
|
||||
}
|
||||
cfClient = CloudFlareClient(proxyProvider, cookieJar, this, url)
|
||||
viewBinding.webView.configureForParser(intent?.getStringExtra(AppRouter.KEY_USER_AGENT))
|
||||
cfClient = CloudFlareClient(cookieJar, this, url)
|
||||
viewBinding.webView.webViewClient = cfClient
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
@@ -106,8 +107,7 @@ class CloudFlareActivity : BaseBrowserActivity(), CloudFlareCallback {
|
||||
|
||||
override fun onTitleChanged(title: CharSequence, subtitle: CharSequence?) {
|
||||
setTitle(title)
|
||||
supportActionBar?.subtitle =
|
||||
subtitle?.toString()?.toHttpUrlOrNull()?.topPrivateDomain() ?: subtitle
|
||||
supportActionBar?.subtitle = subtitle?.toString()?.toHttpUrlOrNull()?.host.ifNullOrEmpty { subtitle }
|
||||
}
|
||||
|
||||
private fun restartCheck() {
|
||||
|
||||
@@ -4,17 +4,15 @@ import android.graphics.Bitmap
|
||||
import android.webkit.WebView
|
||||
import org.koitharu.kotatsu.browser.BrowserClient
|
||||
import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar
|
||||
import org.koitharu.kotatsu.core.network.proxy.ProxyProvider
|
||||
import org.koitharu.kotatsu.parsers.network.CloudFlareHelper
|
||||
|
||||
private const val LOOP_COUNTER = 3
|
||||
|
||||
class CloudFlareClient(
|
||||
proxyProvider: ProxyProvider,
|
||||
private val cookieJar: MutableCookieJar,
|
||||
private val callback: CloudFlareCallback,
|
||||
private val targetUrl: String,
|
||||
) : BrowserClient(proxyProvider, callback) {
|
||||
) : BrowserClient(callback) {
|
||||
|
||||
private val oldClearance = getClearance()
|
||||
private var counter = 0
|
||||
|
||||
@@ -34,7 +34,6 @@ import org.koitharu.kotatsu.settings.search.SettingsItem
|
||||
import org.koitharu.kotatsu.settings.search.SettingsSearchFragment
|
||||
import org.koitharu.kotatsu.settings.search.SettingsSearchViewModel
|
||||
import org.koitharu.kotatsu.settings.sources.SourceSettingsFragment
|
||||
import org.koitharu.kotatsu.settings.sources.SourceSettingsFragment.Companion.EXTRA_SOURCE
|
||||
import org.koitharu.kotatsu.settings.sources.SourcesSettingsFragment
|
||||
import org.koitharu.kotatsu.settings.sources.manage.SourcesManageFragment
|
||||
import org.koitharu.kotatsu.settings.tracker.TrackerSettingsFragment
|
||||
@@ -57,7 +56,7 @@ class SettingsActivity :
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(ActivitySettingsBinding.inflate(layoutInflater))
|
||||
setDisplayHomeAsUp(true, false)
|
||||
setDisplayHomeAsUp(isEnabled = true, showUpAsClose = false)
|
||||
val fm = supportFragmentManager
|
||||
val currentFragment = fm.findFragmentById(R.id.container)
|
||||
if (currentFragment == null || (isMasterDetails && currentFragment is RootSettingsFragment)) {
|
||||
@@ -151,7 +150,7 @@ class SettingsActivity :
|
||||
AppRouter.ACTION_PROXY -> ProxySettingsFragment()
|
||||
AppRouter.ACTION_MANAGE_DOWNLOADS -> DownloadsSettingsFragment()
|
||||
AppRouter.ACTION_SOURCE -> SourceSettingsFragment.newInstance(
|
||||
MangaSource(intent.getStringExtra(EXTRA_SOURCE)),
|
||||
MangaSource(intent.getStringExtra(AppRouter.KEY_SOURCE)),
|
||||
)
|
||||
|
||||
AppRouter.ACTION_MANAGE_SOURCES -> SourcesManageFragment()
|
||||
|
||||
@@ -9,6 +9,7 @@ import dagger.hilt.android.AndroidEntryPoint
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
|
||||
import org.koitharu.kotatsu.core.model.getTitle
|
||||
import org.koitharu.kotatsu.core.nav.AppRouter
|
||||
import org.koitharu.kotatsu.core.nav.router
|
||||
import org.koitharu.kotatsu.core.parser.EmptyMangaRepository
|
||||
import org.koitharu.kotatsu.core.parser.ParserMangaRepository
|
||||
@@ -121,10 +122,8 @@ class SourceSettingsFragment : BasePreferenceFragment(0), Preference.OnPreferenc
|
||||
private const val KEY_AUTH = "auth"
|
||||
private const val KEY_ENABLE = "enable"
|
||||
|
||||
const val EXTRA_SOURCE = "source"
|
||||
|
||||
fun newInstance(source: MangaSource) = SourceSettingsFragment().withArgs(1) {
|
||||
putString(EXTRA_SOURCE, source.name)
|
||||
putString(AppRouter.KEY_SOURCE, source.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import okhttp3.HttpUrl
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.core.nav.AppRouter
|
||||
import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar
|
||||
import org.koitharu.kotatsu.core.parser.CachingMangaRepository
|
||||
import org.koitharu.kotatsu.core.parser.MangaRepository
|
||||
@@ -32,7 +33,7 @@ class SourceSettingsViewModel @Inject constructor(
|
||||
private val mangaSourcesRepository: MangaSourcesRepository,
|
||||
) : BaseViewModel(), SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
val source = MangaSource(savedStateHandle.get<String>(SourceSettingsFragment.EXTRA_SOURCE))
|
||||
val source = MangaSource(savedStateHandle.get<String>(AppRouter.KEY_SOURCE))
|
||||
val repository = mangaRepositoryFactory.create(source)
|
||||
|
||||
val onActionDone = MutableEventFlow<ReversibleAction>()
|
||||
|
||||
@@ -14,46 +14,34 @@ import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.browser.BaseBrowserActivity
|
||||
import org.koitharu.kotatsu.browser.BrowserCallback
|
||||
import org.koitharu.kotatsu.browser.BrowserClient
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.core.model.getTitle
|
||||
import org.koitharu.kotatsu.core.nav.AppRouter
|
||||
import org.koitharu.kotatsu.core.network.CommonHeaders
|
||||
import org.koitharu.kotatsu.core.parser.MangaRepository
|
||||
import org.koitharu.kotatsu.core.parser.ParserMangaRepository
|
||||
import org.koitharu.kotatsu.core.util.ext.configureForParser
|
||||
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
|
||||
import org.koitharu.kotatsu.parsers.MangaParserAuthProvider
|
||||
import org.koitharu.kotatsu.parsers.model.MangaParserSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.settings.sources.SourceSettingsFragment.Companion.EXTRA_SOURCE
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class SourceAuthActivity : BaseBrowserActivity(), BrowserCallback {
|
||||
|
||||
@Inject
|
||||
lateinit var mangaRepositoryFactory: MangaRepository.Factory
|
||||
|
||||
private lateinit var authProvider: MangaParserAuthProvider
|
||||
|
||||
override fun onCreate2(savedInstanceState: Bundle?) {
|
||||
val source = MangaSource(intent?.getStringExtra(EXTRA_SOURCE))
|
||||
if (source !is MangaParserSource) {
|
||||
override fun onCreate2(savedInstanceState: Bundle?, source: MangaSource, repository: ParserMangaRepository?) {
|
||||
if (repository == null) {
|
||||
finishAfterTransition()
|
||||
return
|
||||
}
|
||||
val repository = mangaRepositoryFactory.create(source) as? ParserMangaRepository
|
||||
authProvider = (repository)?.getAuthProvider() ?: run {
|
||||
authProvider = repository.getAuthProvider() ?: run {
|
||||
Toast.makeText(
|
||||
this,
|
||||
getString(R.string.auth_not_supported_by, source.title),
|
||||
getString(R.string.auth_not_supported_by, source.getTitle(this)),
|
||||
Toast.LENGTH_SHORT,
|
||||
).show()
|
||||
finishAfterTransition()
|
||||
return
|
||||
}
|
||||
setDisplayHomeAsUp(true, true)
|
||||
viewBinding.webView.configureForParser(repository.getRequestHeaders()[CommonHeaders.USER_AGENT])
|
||||
viewBinding.webView.webViewClient = BrowserClient(proxyProvider, this)
|
||||
setDisplayHomeAsUp(isEnabled = true, showUpAsClose = true)
|
||||
viewBinding.webView.webViewClient = BrowserClient(this)
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
proxyProvider.applyWebViewConfig()
|
||||
@@ -63,7 +51,7 @@ class SourceAuthActivity : BaseBrowserActivity(), BrowserCallback {
|
||||
if (savedInstanceState == null) {
|
||||
val url = authProvider.authUrl
|
||||
onTitleChanged(
|
||||
source.title,
|
||||
source.getTitle(this@SourceAuthActivity),
|
||||
getString(R.string.loading_),
|
||||
)
|
||||
viewBinding.webView.loadUrl(url)
|
||||
@@ -92,13 +80,10 @@ class SourceAuthActivity : BaseBrowserActivity(), BrowserCallback {
|
||||
}
|
||||
|
||||
class Contract : ActivityResultContract<MangaSource, Boolean>() {
|
||||
override fun createIntent(context: Context, input: MangaSource): Intent {
|
||||
return AppRouter.sourceAuthIntent(context, input)
|
||||
}
|
||||
|
||||
override fun parseResult(resultCode: Int, intent: Intent?): Boolean {
|
||||
return resultCode == RESULT_OK
|
||||
}
|
||||
override fun createIntent(context: Context, input: MangaSource) = AppRouter.sourceAuthIntent(context, input)
|
||||
|
||||
override fun parseResult(resultCode: Int, intent: Intent?) = resultCode == RESULT_OK
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -17,6 +17,7 @@ import coil3.ImageLoader
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.nav.AppRouter
|
||||
import org.koitharu.kotatsu.core.nav.router
|
||||
import org.koitharu.kotatsu.core.os.AppShortcutManager
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
@@ -117,7 +118,7 @@ class SourcesManageFragment :
|
||||
override fun onItemSettingsClick(item: SourceConfigItem.SourceItem) {
|
||||
(activity as? SettingsActivity)?.openFragment(
|
||||
fragmentClass = SourceSettingsFragment::class.java,
|
||||
args = Bundle(1).apply { putString(SourceSettingsFragment.EXTRA_SOURCE, item.source.name) },
|
||||
args = Bundle(1).apply { putString(AppRouter.KEY_SOURCE, item.source.name) },
|
||||
isFromRoot = false,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ material = "1.13.0-alpha12"
|
||||
moshi = "1.15.2"
|
||||
okhttp = "4.12.0"
|
||||
okio = "3.10.2"
|
||||
parsers = "2ec2484982"
|
||||
parsers = "b8376594"
|
||||
preference = "1.2.1"
|
||||
recyclerview = "1.4.0"
|
||||
room = "2.6.1"
|
||||
|
||||
Reference in New Issue
Block a user