|
|
|
@ -2,41 +2,43 @@ package org.koitharu.kotatsu.core.network
|
|
|
|
|
|
|
|
|
|
|
|
import okhttp3.Interceptor
|
|
|
|
import okhttp3.Interceptor
|
|
|
|
import okhttp3.Response
|
|
|
|
import okhttp3.Response
|
|
|
|
import okhttp3.internal.closeQuietly
|
|
|
|
import okio.IOException
|
|
|
|
import org.jsoup.Jsoup
|
|
|
|
|
|
|
|
import org.koitharu.kotatsu.core.exceptions.CloudFlareBlockedException
|
|
|
|
import org.koitharu.kotatsu.core.exceptions.CloudFlareBlockedException
|
|
|
|
import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException
|
|
|
|
import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException
|
|
|
|
import org.koitharu.kotatsu.parsers.model.MangaSource
|
|
|
|
import org.koitharu.kotatsu.parsers.model.MangaSource
|
|
|
|
import java.net.HttpURLConnection.HTTP_FORBIDDEN
|
|
|
|
import org.koitharu.kotatsu.parsers.network.CloudFlareHelper
|
|
|
|
import java.net.HttpURLConnection.HTTP_UNAVAILABLE
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CloudFlareInterceptor : Interceptor {
|
|
|
|
class CloudFlareInterceptor : Interceptor {
|
|
|
|
|
|
|
|
|
|
|
|
override fun intercept(chain: Interceptor.Chain): Response {
|
|
|
|
override fun intercept(chain: Interceptor.Chain): Response {
|
|
|
|
val response = chain.proceed(chain.request())
|
|
|
|
val request = chain.request()
|
|
|
|
if (response.code == HTTP_FORBIDDEN || response.code == HTTP_UNAVAILABLE) {
|
|
|
|
val response = chain.proceed(request)
|
|
|
|
val content = response.body?.let { response.peekBody(Long.MAX_VALUE) }?.byteStream()?.use {
|
|
|
|
return when (CloudFlareHelper.checkResponseForProtection(response)) {
|
|
|
|
Jsoup.parse(it, Charsets.UTF_8.name(), response.request.url.toString())
|
|
|
|
CloudFlareHelper.PROTECTION_BLOCKED -> response.closeThrowing(
|
|
|
|
} ?: return response
|
|
|
|
CloudFlareBlockedException(
|
|
|
|
val hasCaptcha = content.getElementById("challenge-error-title") != null
|
|
|
|
|
|
|
|
val isBlocked = content.selectFirst("h2[data-translate=\"blocked_why_headline\"]") != null
|
|
|
|
|
|
|
|
if (hasCaptcha || isBlocked) {
|
|
|
|
|
|
|
|
val request = response.request
|
|
|
|
|
|
|
|
response.closeQuietly()
|
|
|
|
|
|
|
|
if (isBlocked) {
|
|
|
|
|
|
|
|
throw CloudFlareBlockedException(
|
|
|
|
|
|
|
|
url = request.url.toString(),
|
|
|
|
url = request.url.toString(),
|
|
|
|
source = request.tag(MangaSource::class.java),
|
|
|
|
source = request.tag(MangaSource::class.java),
|
|
|
|
|
|
|
|
),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
|
|
|
|
throw CloudFlareProtectedException(
|
|
|
|
CloudFlareHelper.PROTECTION_CAPTCHA -> response.closeThrowing(
|
|
|
|
|
|
|
|
CloudFlareProtectedException(
|
|
|
|
url = request.url.toString(),
|
|
|
|
url = request.url.toString(),
|
|
|
|
source = request.tag(MangaSource::class.java),
|
|
|
|
source = request.tag(MangaSource::class.java),
|
|
|
|
headers = request.headers,
|
|
|
|
headers = request.headers,
|
|
|
|
|
|
|
|
),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
else -> response
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private fun Response.closeThrowing(error: IOException): Nothing {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
close()
|
|
|
|
|
|
|
|
} catch (e: Exception) {
|
|
|
|
|
|
|
|
error.addSuppressed(e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return response
|
|
|
|
throw error
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|