1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2026-01-01 10:59:20 +00:00

Compare commits

...

5 Commits

5 changed files with 52 additions and 43 deletions

View File

@@ -7,6 +7,7 @@
* `MicroUtils`: `0.12.1` -> `0.12.4` * `MicroUtils`: `0.12.1` -> `0.12.4`
* `Core`: * `Core`:
* `SetWebhook#allowedUpdates` now is `ALL_UPDATES_LIST` by default instead of `null` * `SetWebhook#allowedUpdates` now is `ALL_UPDATES_LIST` by default instead of `null`
* `KtorRequestsExecutor#execute` now will __always__ throw `BotException` if something went wrong inside
* `API`: * `API`:
* Extension `TelegramBot#setWebhook` parameter `allowedUpdates` now is `ALL_UPDATES_LIST` by default instead of `null` * Extension `TelegramBot#setWebhook` parameter `allowedUpdates` now is `ALL_UPDATES_LIST` by default instead of `null`
* `Utils`: * `Utils`:

View File

@@ -40,7 +40,7 @@ suspend fun BehaviourContext.waitCommandMessage(
) = waitCommandMessage(Regex(command), initRequest, errorFactory) ) = waitCommandMessage(Regex(command), initRequest, errorFactory)
fun Flow<CommonMessage<TextContent>>.requireCommandAtStart() = filter { fun Flow<CommonMessage<TextContent>>.requireCommandAtStart() = filter {
(it.content.textSources.firstOrNull() as? BotCommandTextSource) != null it.content.textSources.firstOrNull() is BotCommandTextSource
} }
/** /**
@@ -61,7 +61,7 @@ fun Flow<CommonMessage<TextContent>>.requireSingleCommand() = filter {
} }
} }
true count == 1
} }
/** /**

View File

@@ -35,13 +35,18 @@ fun newRequestException(
} }
} ?: CommonRequestException(response, plainAnswer, message, cause) } ?: CommonRequestException(response, plainAnswer, message, cause)
sealed class BotException(message: String = "Something went wrong", cause: Throwable? = null) : IOException(message, cause)
class CommonBotException(message: String = "Something went wrong", cause: Throwable? = null) : BotException(message, cause)
sealed class RequestException constructor( sealed class RequestException constructor(
val response: Response, val response: Response,
val plainAnswer: String, val plainAnswer: String,
message: String? = null, message: String? = null,
override val cause: Throwable? = null cause: Throwable? = null
) : IOException( ) : BotException(
message ?: "Something went wrong" message ?: "Something went wrong",
cause
) )
class CommonRequestException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) : class CommonRequestException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) :

View File

@@ -1,9 +1,10 @@
package dev.inmo.tgbotapi.bot.ktor package dev.inmo.tgbotapi.bot.ktor
import dev.inmo.micro_utils.coroutines.runCatchingSafely
import dev.inmo.micro_utils.coroutines.safely import dev.inmo.micro_utils.coroutines.safely
import dev.inmo.tgbotapi.bot.BaseRequestsExecutor import dev.inmo.tgbotapi.bot.BaseRequestsExecutor
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.bot.exceptions.newRequestException import dev.inmo.tgbotapi.bot.exceptions.*
import dev.inmo.tgbotapi.bot.ktor.base.* import dev.inmo.tgbotapi.bot.ktor.base.*
import dev.inmo.tgbotapi.bot.settings.limiters.ExceptionsOnlyLimiter import dev.inmo.tgbotapi.bot.settings.limiters.ExceptionsOnlyLimiter
import dev.inmo.tgbotapi.bot.settings.limiters.RequestLimiter import dev.inmo.tgbotapi.bot.settings.limiters.RequestLimiter
@@ -48,12 +49,36 @@ class KtorRequestsExecutor(
} }
override suspend fun <T : Any> execute(request: Request<T>): T { override suspend fun <T : Any> execute(request: Request<T>): T {
return runCatching { return runCatchingSafely {
safely( pipelineStepsHolder.onBeforeSearchCallFactory(request, callsFactories)
{ e -> requestsLimiter.limit {
pipelineStepsHolder.onRequestException(request, e) ?.let { return@safely it } var result: T? = null
lateinit var factoryHandledRequest: KtorCallFactory
for (potentialFactory in callsFactories) {
pipelineStepsHolder.onBeforeCallFactoryMakeCall(request, potentialFactory)
result = potentialFactory.makeCall(
client,
telegramAPIUrlsKeeper,
request,
jsonFormatter
)
result = pipelineStepsHolder.onAfterCallFactoryMakeCall(result, request, potentialFactory)
if (result != null) {
factoryHandledRequest = potentialFactory
break
}
}
throw if (e is ClientRequestException) { result ?.let {
pipelineStepsHolder.onRequestResultPresented(it, request, factoryHandledRequest, callsFactories)
} ?: pipelineStepsHolder.onRequestResultAbsent(request, callsFactories) ?: error("Can't execute request: $request")
}
}.let {
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 content = e.response.bodyAsText()
val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content) val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content)
newRequestException( newRequestException(
@@ -61,38 +86,15 @@ class KtorRequestsExecutor(
content, content,
"Can't get result object from $content" "Can't get result object from $content"
) )
} else {
e
} }
exceptionResult.exceptionOrNull() ?.let {
CommonBotException(cause = e)
} ?: exceptionResult.getOrThrow()
} else {
CommonBotException(cause = e)
} }
) { } ?.let { Result.failure(it) } ?: it
pipelineStepsHolder.onBeforeSearchCallFactory(request, callsFactories) pipelineStepsHolder.onRequestReturnResult(result, request, callsFactories)
requestsLimiter.limit {
var result: T? = null
lateinit var factoryHandledRequest: KtorCallFactory
for (potentialFactory in callsFactories) {
pipelineStepsHolder.onBeforeCallFactoryMakeCall(request, potentialFactory)
result = potentialFactory.makeCall(
client,
telegramAPIUrlsKeeper,
request,
jsonFormatter
)
result = pipelineStepsHolder.onAfterCallFactoryMakeCall(result, request, potentialFactory)
if (result != null) {
factoryHandledRequest = potentialFactory
break
}
}
result ?.let {
pipelineStepsHolder.onRequestResultPresented(it, request, factoryHandledRequest, callsFactories)
} ?: pipelineStepsHolder.onRequestResultAbsent(request, callsFactories) ?: error("Can't execute request: $request")
}
}
}.let {
pipelineStepsHolder.onRequestReturnResult(it, request, callsFactories)
} }
} }

View File

@@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.types.message.textsources package dev.inmo.tgbotapi.types.message.textsources
import dev.inmo.tgbotapi.types.usernameRegex import dev.inmo.tgbotapi.types.usernameRegex
import dev.inmo.tgbotapi.types.Username
import dev.inmo.tgbotapi.utils.RiskFeature import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.internal.* import dev.inmo.tgbotapi.utils.internal.*
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@@ -17,8 +18,8 @@ data class BotCommandTextSource @RiskFeature(DirectInvocationOfTextSourceConstru
val command: String by lazy { val command: String by lazy {
commandRegex.find(source) ?.value ?.substring(1) ?: source.substring(1)// skip first symbol like "/" or "!" commandRegex.find(source) ?.value ?.substring(1) ?: source.substring(1)// skip first symbol like "/" or "!"
} }
val username: String? by lazy { val username: Username? by lazy {
usernameRegex.find(source) ?.value ?.substring(1) ?: source.substring(1)// skip first symbol "@" Username(usernameRegex.find(source) ?.value ?: return@lazy null)
} }
override val markdown: String by lazy { source.commandMarkdown() } override val markdown: String by lazy { source.commandMarkdown() }