mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2025-09-15 21:29:25 +00:00
add middlewares
This commit is contained in:
@@ -3,6 +3,7 @@ package dev.inmo.tgbotapi.bot.ktor
|
||||
import dev.inmo.kslog.common.KSLog
|
||||
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||
import dev.inmo.tgbotapi.bot.ktor.base.*
|
||||
import dev.inmo.tgbotapi.bot.ktor.middlewares.TelegramBotMiddlewaresPipelinesHandler
|
||||
import dev.inmo.tgbotapi.bot.settings.limiters.ExceptionsOnlyLimiter
|
||||
import dev.inmo.tgbotapi.bot.settings.limiters.RequestLimiter
|
||||
import dev.inmo.tgbotapi.utils.*
|
||||
@@ -28,6 +29,10 @@ class KtorRequestsExecutorBuilder(
|
||||
var logger: KSLog = DefaultKTgBotAPIKSLog
|
||||
var pipelineStepsHolder: TelegramBotPipelinesHandler = TelegramBotPipelinesHandler
|
||||
|
||||
fun includeMiddlewares(block: TelegramBotMiddlewaresPipelinesHandler.Builder.() -> Unit) {
|
||||
pipelineStepsHolder = TelegramBotMiddlewaresPipelinesHandler.build(block)
|
||||
}
|
||||
|
||||
fun build() = KtorRequestsExecutor(
|
||||
telegramAPIUrlsKeeper,
|
||||
client,
|
||||
|
@@ -68,7 +68,7 @@ interface TelegramBotPipelinesHandler {
|
||||
result: Result<T>,
|
||||
request: Request<T>,
|
||||
callsFactories: List<KtorCallFactory>
|
||||
): Result<T> = result.getOrThrow()
|
||||
): Result<T> = result
|
||||
|
||||
companion object : TelegramBotPipelinesHandler
|
||||
}
|
||||
|
@@ -4,6 +4,22 @@ import dev.inmo.tgbotapi.bot.ktor.KtorCallFactory
|
||||
import dev.inmo.tgbotapi.bot.ktor.TelegramBotPipelinesHandler
|
||||
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||
|
||||
/**
|
||||
* @param onRequestException Will be called when some exception happen during [Request] handling. Non-null result of
|
||||
* lambda will be used as the result of request handling
|
||||
* @param onBeforeSearchCallFactory Will be called when telegram bot starts to choose which [KtorCallFactory] will handle
|
||||
* [Request]
|
||||
* @param onBeforeCallFactoryMakeCall Will be called when telegram bot trying to use [KtorCallFactory] as potential
|
||||
* handler for [Request]
|
||||
* @param onAfterCallFactoryMakeCall Will be called when [KtorCallFactory] made call. Non-null result of
|
||||
* lambda will be used as the result of request handling
|
||||
* @param onRequestResultPresented Will be called when [KtorCallFactory] **or** [TelegramBotPipelinesHandler]/[TelegramBotMiddleware]
|
||||
* returned non-null result. Non-null result of lambda will be used as the result of request handling
|
||||
* @param onRequestResultAbsent Will be called when some there is no any result of [Request] handling. Non-null result of
|
||||
* lambda will be used as the result of request handling
|
||||
* @param onRequestReturnResult Latest lambda before result returning. Will be called after all previous stages.
|
||||
* Non-null result of lambda will be used as the result of request handling
|
||||
*/
|
||||
class TelegramBotMiddleware(
|
||||
internal val onRequestException: (suspend (request: Request<*>, t: Throwable?) -> Any?)? = null,
|
||||
internal val onBeforeSearchCallFactory: (suspend (request: Request<*>, callsFactories: List<KtorCallFactory>) -> Unit)? = null,
|
||||
|
@@ -8,15 +8,21 @@ class TelegramBotMiddlewaresPipelinesHandler(
|
||||
private val middlewares: List<TelegramBotMiddleware>
|
||||
) : TelegramBotPipelinesHandler {
|
||||
override suspend fun <T : Any> onRequestException(request: Request<T>, t: Throwable): T? {
|
||||
return super.onRequestException(request, t)
|
||||
return middlewares.firstNotNullOfOrNull {
|
||||
it.onRequestException(request, t)
|
||||
} ?: super.onRequestException(request, t)
|
||||
}
|
||||
|
||||
override suspend fun onBeforeSearchCallFactory(request: Request<*>, callsFactories: List<KtorCallFactory>) {
|
||||
super.onBeforeSearchCallFactory(request, callsFactories)
|
||||
middlewares.forEach {
|
||||
it.onBeforeSearchCallFactory(request, callsFactories)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun onBeforeCallFactoryMakeCall(request: Request<*>, potentialFactory: KtorCallFactory) {
|
||||
super.onBeforeCallFactoryMakeCall(request, potentialFactory)
|
||||
middlewares.forEach {
|
||||
it.onBeforeCallFactoryMakeCall(request, potentialFactory)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun <T : Any> onAfterCallFactoryMakeCall(
|
||||
@@ -24,7 +30,9 @@ class TelegramBotMiddlewaresPipelinesHandler(
|
||||
request: Request<T>,
|
||||
potentialFactory: KtorCallFactory
|
||||
): T? {
|
||||
return super.onAfterCallFactoryMakeCall(result, request, potentialFactory)
|
||||
return middlewares.firstNotNullOfOrNull {
|
||||
it.onAfterCallFactoryMakeCall(result, request, potentialFactory)
|
||||
} ?: super.onAfterCallFactoryMakeCall(result, request, potentialFactory)
|
||||
}
|
||||
|
||||
override suspend fun <T : Any> onRequestResultPresented(
|
||||
@@ -33,14 +41,18 @@ class TelegramBotMiddlewaresPipelinesHandler(
|
||||
resultCallFactory: KtorCallFactory,
|
||||
callsFactories: List<KtorCallFactory>
|
||||
): T? {
|
||||
return super.onRequestResultPresented(result, request, resultCallFactory, callsFactories)
|
||||
return middlewares.firstNotNullOfOrNull {
|
||||
it.onRequestResultPresented(result, request, resultCallFactory, callsFactories)
|
||||
} ?: super.onRequestResultPresented(result, request, resultCallFactory, callsFactories)
|
||||
}
|
||||
|
||||
override suspend fun <T : Any> onRequestResultAbsent(
|
||||
request: Request<T>,
|
||||
callsFactories: List<KtorCallFactory>
|
||||
): T? {
|
||||
return super.onRequestResultAbsent(request, callsFactories)
|
||||
return middlewares.firstNotNullOfOrNull {
|
||||
it.onRequestResultAbsent(request, callsFactories)
|
||||
} ?: super.onRequestResultAbsent(request, callsFactories)
|
||||
}
|
||||
|
||||
override suspend fun <T : Any> onRequestReturnResult(
|
||||
@@ -48,6 +60,27 @@ class TelegramBotMiddlewaresPipelinesHandler(
|
||||
request: Request<T>,
|
||||
callsFactories: List<KtorCallFactory>
|
||||
): Result<T> {
|
||||
return super.onRequestReturnResult(result, request, callsFactories)
|
||||
return middlewares.firstNotNullOfOrNull {
|
||||
it.onRequestReturnResult(result, request, callsFactories).takeIf {
|
||||
it.onFailure { return@takeIf it !is TelegramBotMiddleware.ResultAbsence }
|
||||
true
|
||||
}
|
||||
} ?: super.onRequestReturnResult(result, request, callsFactories)
|
||||
}
|
||||
|
||||
class Builder {
|
||||
val middlewares = mutableListOf<TelegramBotMiddleware>()
|
||||
|
||||
fun addMiddleware(block: TelegramBotMiddlewareBuilder.() -> Unit) = middlewares.add(
|
||||
TelegramBotMiddleware.build(block)
|
||||
)
|
||||
|
||||
fun build(): TelegramBotMiddlewaresPipelinesHandler = TelegramBotMiddlewaresPipelinesHandler(
|
||||
middlewares.toList()
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun build(block: Builder.() -> Unit) = Builder().apply(block).build()
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user