diff --git a/CHANGELOG.md b/CHANGELOG.md index 46dc7feca4..2980780c81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # TelegramBotAPI changelog +## 3.2.5 + +* `Common`: + * Improve support of new exceptions recovering mechanism + ## 3.2.4 * `API`: diff --git a/gradle.properties b/gradle.properties index bb3496928c..81d9914db5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,4 +6,4 @@ kotlin.incremental=true kotlin.incremental.js=true library_group=dev.inmo -library_version=3.2.4 +library_version=3.2.5 diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/exceptions/RequestException.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/exceptions/RequestException.kt index 7448d2e901..439af142ed 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/exceptions/RequestException.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/exceptions/RequestException.kt @@ -4,6 +4,7 @@ import com.soywiz.klock.DateTime import dev.inmo.tgbotapi.types.Response import dev.inmo.tgbotapi.types.RetryAfterError import io.ktor.utils.io.errors.IOException +import kotlinx.coroutines.CopyableThrowable fun newRequestException( response: Response, @@ -35,9 +36,11 @@ fun newRequestException( } } ?: CommonRequestException(response, plainAnswer, message, cause) -sealed class BotException(message: String = "Something went wrong", cause: Throwable? = null) : IOException(message, cause) +sealed class BotException(message: String = "Something went wrong", cause: Throwable? = null) : IOException(message, cause), CopyableThrowable -class CommonBotException(message: String = "Something went wrong", cause: Throwable? = null) : BotException(message, cause) +class CommonBotException(message: String = "Something went wrong", cause: Throwable? = null) : BotException(message, cause) { + override fun createCopy(): BotException = CommonBotException(message!!, cause) +} sealed class RequestException constructor( val response: Response, @@ -50,28 +53,46 @@ sealed class RequestException constructor( ) class CommonRequestException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) : - RequestException(response, plainAnswer, message, cause) + RequestException(response, plainAnswer, message, cause) { + override fun createCopy(): BotException = CommonRequestException(response, plainAnswer, message, cause) +} class UnauthorizedException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) : - RequestException(response, plainAnswer, message, cause) + RequestException(response, plainAnswer, message, cause) { + override fun createCopy(): BotException = UnauthorizedException(response, plainAnswer, message, cause) +} class ReplyMessageNotFoundException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) : - RequestException(response, plainAnswer, message, cause) + RequestException(response, plainAnswer, message, cause) { + override fun createCopy(): BotException = ReplyMessageNotFoundException(response, plainAnswer, message, cause) +} class MessageIsNotModifiedException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) : - RequestException(response, plainAnswer, message, cause) + RequestException(response, plainAnswer, message, cause) { + override fun createCopy(): BotException = MessageIsNotModifiedException(response, plainAnswer, message, cause) +} class MessageToEditNotFoundException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) : - RequestException(response, plainAnswer, message, cause) + RequestException(response, plainAnswer, message, cause) { + override fun createCopy(): BotException = MessageToEditNotFoundException(response, plainAnswer, message, cause) +} class InvalidPhotoDimensionsException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) : - RequestException(response, plainAnswer, message, cause) + RequestException(response, plainAnswer, message, cause) { + override fun createCopy(): BotException = InvalidPhotoDimensionsException(response, plainAnswer, message, cause) +} class WrongFileIdentifierException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) : - RequestException(response, plainAnswer, message, cause) + RequestException(response, plainAnswer, message, cause) { + override fun createCopy(): BotException = WrongFileIdentifierException(response, plainAnswer, message, cause) +} class TooMuchRequestsException(val retryAfter: RetryAfterError, response: Response, plainAnswer: String, message: String?, cause: Throwable?) : - RequestException(response, plainAnswer, message, cause) + RequestException(response, plainAnswer, message, cause) { + override fun createCopy(): BotException = TooMuchRequestsException(retryAfter, response, plainAnswer, message, cause) +} class GetUpdatesConflict(response: Response, plainAnswer: String, message: String?, cause: Throwable?) : - RequestException(response, plainAnswer, message, cause) + RequestException(response, plainAnswer, message, cause) { + override fun createCopy(): BotException = GetUpdatesConflict(response, plainAnswer, message, cause) +} diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/KtorRequestsExecutor.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/KtorRequestsExecutor.kt index 03ab290421..c9a3663fe5 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/KtorRequestsExecutor.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/KtorRequestsExecutor.kt @@ -77,21 +77,23 @@ class KtorRequestsExecutor( val result = it.exceptionOrNull() ?.let { e -> pipelineStepsHolder.onRequestException(request, e) ?.let { return@let it } - if (e is ClientRequestException) { - val exceptionResult = runCatchingSafely { - val content = e.response.bodyAsText() - val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content) - newRequestException( - responseObject, - content, - "Can't get result object from $content" - ) + when (e) { + is ClientRequestException -> { + val exceptionResult = runCatchingSafely { + val content = e.response.bodyAsText() + val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content) + newRequestException( + responseObject, + content, + "Can't get result object from $content" + ) + } + exceptionResult.exceptionOrNull() ?.let { + CommonBotException(cause = e) + } ?: exceptionResult.getOrThrow() } - exceptionResult.exceptionOrNull() ?.let { - CommonBotException(cause = e) - } ?: exceptionResult.getOrThrow() - } else { - CommonBotException(cause = e) + is BotException -> e + else -> CommonBotException(cause = e) } } ?.let { Result.failure(it) } ?: it pipelineStepsHolder.onRequestReturnResult(result, request, callsFactories) diff --git a/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/updates/retrieving/LongPolling.kt b/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/updates/retrieving/LongPolling.kt index 830f37f0c3..3e9f27dfaa 100644 --- a/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/updates/retrieving/LongPolling.kt +++ b/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/updates/retrieving/LongPolling.kt @@ -3,8 +3,7 @@ package dev.inmo.tgbotapi.extensions.utils.updates.retrieving import dev.inmo.micro_utils.coroutines.* import dev.inmo.tgbotapi.bot.RequestsExecutor import dev.inmo.tgbotapi.bot.TelegramBot -import dev.inmo.tgbotapi.bot.exceptions.GetUpdatesConflict -import dev.inmo.tgbotapi.bot.exceptions.RequestException +import dev.inmo.tgbotapi.bot.exceptions.* import dev.inmo.tgbotapi.extensions.utils.updates.convertWithMediaGroupUpdates import dev.inmo.tgbotapi.extensions.utils.updates.lastUpdateIdentifier import dev.inmo.tgbotapi.requests.GetUpdates @@ -101,10 +100,10 @@ fun TelegramBot.createAccumulatedUpdatesRetrieverFlow( ): Flow = longPollingFlow( timeoutSeconds = 0, exceptionsHandler = { - if (it is HttpRequestTimeoutException) { - throw CancellationException("Cancel due to absence of new updates") - } else { - exceptionsHandler ?.invoke(it) + when { + it is HttpRequestTimeoutException || + (it is CommonBotException && it.cause is HttpRequestTimeoutException) -> throw CancellationException("Cancel due to absence of new updates") + else -> exceptionsHandler ?.invoke(it) } }, allowedUpdates = allowedUpdates