From f91ff0b9d04016d460cf6dbf088c2eb1e4316c24 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Tue, 20 Aug 2024 14:28:07 +0300 Subject: [PATCH] [ExHentai] Detect IP ban --- .../exception/TooManyRequestExceptions.kt | 17 +++++++++++ .../parsers/site/all/ExHentaiParser.kt | 28 ++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 src/main/kotlin/org/koitharu/kotatsu/parsers/exception/TooManyRequestExceptions.kt diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/exception/TooManyRequestExceptions.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/exception/TooManyRequestExceptions.kt new file mode 100644 index 00000000..d0650b48 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/exception/TooManyRequestExceptions.kt @@ -0,0 +1,17 @@ +package org.koitharu.kotatsu.parsers.exception + +import okio.IOException +import java.time.Instant + +class TooManyRequestExceptions( + val url: String, + val retryAfter: Long, +) : IOException() { + + val retryAt: Instant? + get() = if (retryAfter > 0 && retryAfter < Long.MAX_VALUE) { + Instant.now().plusMillis(retryAfter) + } else { + null + } +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/ExHentaiParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/ExHentaiParser.kt index 89a08531..1c26b2f6 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/ExHentaiParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/ExHentaiParser.kt @@ -5,6 +5,10 @@ import androidx.collection.ArraySet import androidx.collection.SparseArrayCompat import androidx.collection.set import okhttp3.HttpUrl.Companion.toHttpUrlOrNull +import okhttp3.Interceptor +import okhttp3.Response +import okhttp3.internal.headersContentLength +import org.intellij.lang.annotations.Language import org.jsoup.internal.StringUtil import org.jsoup.nodes.Element import org.koitharu.kotatsu.parsers.MangaLoaderContext @@ -13,9 +17,12 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.PagedMangaParser import org.koitharu.kotatsu.parsers.config.ConfigKey import org.koitharu.kotatsu.parsers.exception.AuthRequiredException +import org.koitharu.kotatsu.parsers.exception.TooManyRequestExceptions import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.util.* import java.util.* +import java.util.Collections.emptyList +import java.util.concurrent.TimeUnit import kotlin.math.pow private const val DOMAIN_UNAUTHORIZED = "e-hentai.org" @@ -24,7 +31,7 @@ private const val DOMAIN_AUTHORIZED = "exhentai.org" @MangaSourceParser("EXHENTAI", "ExHentai", type = ContentType.HENTAI) internal class ExHentaiParser( context: MangaLoaderContext, -) : PagedMangaParser(context, MangaParserSource.EXHENTAI, pageSize = 25), MangaParserAuthProvider { +) : PagedMangaParser(context, MangaParserSource.EXHENTAI, pageSize = 25), MangaParserAuthProvider, Interceptor { override val availableSortOrders: Set = setOf(SortOrder.NEWEST) override val isTagsExclusionSupported: Boolean = true @@ -309,6 +316,25 @@ internal class ExHentaiParser( Locale("vi"), ) + override fun intercept(chain: Interceptor.Chain): Response { + val response = chain.proceed(chain.request()) + if (response.headersContentLength() <= 256) { + val text = response.peekBody(256).string() + if (text.startsWith("Your IP address has been temporarily banned")) { + @Language("RegExp") + val regex = kotlin.text.Regex("ban expires in ([0-9]+) minutes? and ([0-9]+) seconds?") + val groups = regex.find(text)?.groupValues ?: return response + val minutes = groups.getOrNull(1)?.toLongOrNull() ?: 0L + val seconds = groups.getOrNull(2)?.toLongOrNull() ?: 0L + throw TooManyRequestExceptions( + url = response.request.url.toString(), + retryAfter = TimeUnit.MINUTES.toMillis(minutes) + TimeUnit.SECONDS.toMillis(seconds), + ) + } + } + return response + } + private fun Locale.toLanguagePath() = when (language) { else -> getDisplayLanguage(Locale.ENGLISH).lowercase() }