1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2025-11-19 13:55:57 +00:00

Compare commits

...

17 Commits

Author SHA1 Message Date
2052072e5d fix in changelog 2024-10-31 13:25:40 +06:00
6fb3d3fcb1 fill changelog and get back webhooks to old looks like 2024-10-31 13:24:47 +06:00
9c5793bec7 change task used for ksp generation 2024-10-30 18:57:47 +06:00
fd9bff611b small prenote in changelog 2024-10-30 15:17:05 +06:00
bb66279044 jvmApiDump 2024-10-30 15:15:49 +06:00
24b48f2536 update dependencies 2024-10-30 15:14:52 +06:00
670c26c982 Merge pull request #912 from d1snin/18.2.3
Migrate to ktor 3.0.0
2024-10-30 15:13:33 +06:00
7ed5d9ceed start 19.0.0 2024-10-30 14:53:04 +06:00
787941fcaf Merge pull request #911 from InsanusMokrassar/18.2.3
18.2.3
2024-10-30 14:51:44 +06:00
6c9f1bc016 get back default list of middlewares 2024-10-30 14:41:22 +06:00
e5bffa7c51 upgrade onRequestResultPresented in middlewares 2024-10-30 13:53:36 +06:00
d1snin
3fe26b057a migrate to ktor 3.0.0 2024-10-27 05:43:27 +03:00
dccd15a5e9 jvmApiDump 2024-10-24 23:13:12 +06:00
3d14c93d89 make DefaultKtorRequestsExecutor now uses runCatching instead of runCatchingSafely 2024-10-24 22:53:34 +06:00
b8a6534b6a add ExceptionsThrottlerTelegramBotMiddleware 2024-10-24 22:49:28 +06:00
f5529033ec start 18.2.3 2024-10-24 21:54:20 +06:00
482c375327 Merge pull request #909 from InsanusMokrassar/18.2.2
18.2.2
2024-10-21 18:26:54 +06:00
18 changed files with 201 additions and 85 deletions

View File

@@ -17,7 +17,7 @@ jobs:
rm gradle.properties rm gradle.properties
mv gradle.properties.tmp gradle.properties mv gradle.properties.tmp gradle.properties
- name: KotlinSymbolProcessing execution - name: KotlinSymbolProcessing execution
run: ./gradlew ksp run: ./gradlew kspCommonMainKotlinMetadata
- name: Build - name: Build
run: ./gradlew build run: ./gradlew build
- name: API compatibility check - name: API compatibility check

View File

@@ -1,5 +1,23 @@
# TelegramBotAPI changelog # TelegramBotAPI changelog
## 19.0.0
**THIS UPDATE CONTAINS BREAKING CHANGES**
**THIS UPDATE CONTAINS UPGRADE UP TO KTOR 3.0 (thanks to [@d1snin](https://github.com/d1snin))**
* `Version`:
* `Ktor`: `2.3.12` -> `3.0.1`
* `MicroUtils`: `0.22.7` -> `0.23.0`
## 18.2.3
* `Core`:
* Add default middleware `ExceptionsThrottlerTelegramBotMiddleware`
* Make `TelegramBotMiddlewaresPipelinesHandler` to be default `TelegramBotPipelinesHandler`
* Make `DefaultKtorRequestsExecutor` now uses `runCatching` instead of `runCatchingSafely`
* `onRequestResultPresented` lambda now accepts non-nullable `result`
## 18.2.2 ## 18.2.2
* `Version`: * `Version`:

View File

@@ -6,4 +6,4 @@ kotlin.incremental=true
kotlin.incremental.js=true kotlin.incremental.js=true
library_group=dev.inmo library_group=dev.inmo
library_version=18.2.2 library_version=19.0.0

View File

@@ -8,12 +8,12 @@ javax-activation = "1.1.1"
korlibs = "5.4.0" korlibs = "5.4.0"
uuid = "0.8.4" uuid = "0.8.4"
ktor = "2.3.12" ktor = "3.0.1"
ksp = "2.0.21-1.0.25" ksp = "2.0.21-1.0.26"
kotlin-poet = "1.18.1" kotlin-poet = "1.18.1"
microutils = "0.22.7" microutils = "0.23.0"
kslog = "1.3.6" kslog = "1.3.6"
versions = "0.51.0" versions = "0.51.0"

View File

@@ -426,11 +426,12 @@ public final class dev/inmo/tgbotapi/bot/ktor/base/SimpleRequestCallFactory : de
public synthetic fun <init> (Ldev/inmo/kslog/common/KSLog;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public synthetic fun <init> (Ldev/inmo/kslog/common/KSLog;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
} }
public final class dev/inmo/tgbotapi/bot/ktor/middlewares/TelegramBotMiddleware : dev/inmo/tgbotapi/bot/ktor/TelegramBotPipelinesHandler { public class dev/inmo/tgbotapi/bot/ktor/middlewares/TelegramBotMiddleware : dev/inmo/tgbotapi/bot/ktor/TelegramBotPipelinesHandler {
public static final field Companion Ldev/inmo/tgbotapi/bot/ktor/middlewares/TelegramBotMiddleware$Companion; public static final field Companion Ldev/inmo/tgbotapi/bot/ktor/middlewares/TelegramBotMiddleware$Companion;
public fun <init> ()V public fun <init> ()V
public fun <init> (Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function5;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function4;)V public fun <init> (Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function5;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function4;Ljava/lang/String;)V
public synthetic fun <init> (Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function5;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function4;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public synthetic fun <init> (Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function5;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function4;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getId ()Ljava/lang/String;
public fun onAfterCallFactoryMakeCall (Ljava/lang/Object;Ldev/inmo/tgbotapi/requests/abstracts/Request;Ldev/inmo/tgbotapi/bot/ktor/KtorCallFactory;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun onAfterCallFactoryMakeCall (Ljava/lang/Object;Ldev/inmo/tgbotapi/requests/abstracts/Request;Ldev/inmo/tgbotapi/bot/ktor/KtorCallFactory;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun onBeforeCallFactoryMakeCall (Ldev/inmo/tgbotapi/requests/abstracts/Request;Ldev/inmo/tgbotapi/bot/ktor/KtorCallFactory;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun onBeforeCallFactoryMakeCall (Ldev/inmo/tgbotapi/requests/abstracts/Request;Ldev/inmo/tgbotapi/bot/ktor/KtorCallFactory;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun onBeforeSearchCallFactory (Ldev/inmo/tgbotapi/requests/abstracts/Request;Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun onBeforeSearchCallFactory (Ldev/inmo/tgbotapi/requests/abstracts/Request;Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
@@ -459,6 +460,7 @@ public final class dev/inmo/tgbotapi/bot/ktor/middlewares/TelegramBotMiddlewareB
public final fun doOnRequestResultAbsent (Lkotlin/jvm/functions/Function3;)V public final fun doOnRequestResultAbsent (Lkotlin/jvm/functions/Function3;)V
public final fun doOnRequestResultPresented (Lkotlin/jvm/functions/Function5;)V public final fun doOnRequestResultPresented (Lkotlin/jvm/functions/Function5;)V
public final fun doOnRequestReturnResult (Lkotlin/jvm/functions/Function4;)V public final fun doOnRequestReturnResult (Lkotlin/jvm/functions/Function4;)V
public final fun getId ()Ljava/lang/String;
public final fun getOnAfterCallFactoryMakeCall ()Lkotlin/jvm/functions/Function4; public final fun getOnAfterCallFactoryMakeCall ()Lkotlin/jvm/functions/Function4;
public final fun getOnBeforeCallFactoryMakeCall ()Lkotlin/jvm/functions/Function3; public final fun getOnBeforeCallFactoryMakeCall ()Lkotlin/jvm/functions/Function3;
public final fun getOnBeforeSearchCallFactory ()Lkotlin/jvm/functions/Function3; public final fun getOnBeforeSearchCallFactory ()Lkotlin/jvm/functions/Function3;
@@ -466,6 +468,7 @@ public final class dev/inmo/tgbotapi/bot/ktor/middlewares/TelegramBotMiddlewareB
public final fun getOnRequestResultAbsent ()Lkotlin/jvm/functions/Function3; public final fun getOnRequestResultAbsent ()Lkotlin/jvm/functions/Function3;
public final fun getOnRequestResultPresented ()Lkotlin/jvm/functions/Function5; public final fun getOnRequestResultPresented ()Lkotlin/jvm/functions/Function5;
public final fun getOnRequestReturnResult ()Lkotlin/jvm/functions/Function4; public final fun getOnRequestReturnResult ()Lkotlin/jvm/functions/Function4;
public final fun setId (Ljava/lang/String;)V
public final fun setOnAfterCallFactoryMakeCall (Lkotlin/jvm/functions/Function4;)V public final fun setOnAfterCallFactoryMakeCall (Lkotlin/jvm/functions/Function4;)V
public final fun setOnBeforeCallFactoryMakeCall (Lkotlin/jvm/functions/Function3;)V public final fun setOnBeforeCallFactoryMakeCall (Lkotlin/jvm/functions/Function3;)V
public final fun setOnBeforeSearchCallFactory (Lkotlin/jvm/functions/Function3;)V public final fun setOnBeforeSearchCallFactory (Lkotlin/jvm/functions/Function3;)V
@@ -481,7 +484,9 @@ public final class dev/inmo/tgbotapi/bot/ktor/middlewares/TelegramBotMiddlewareB
public final class dev/inmo/tgbotapi/bot/ktor/middlewares/TelegramBotMiddlewaresPipelinesHandler : dev/inmo/tgbotapi/bot/ktor/TelegramBotPipelinesHandler { public final class dev/inmo/tgbotapi/bot/ktor/middlewares/TelegramBotMiddlewaresPipelinesHandler : dev/inmo/tgbotapi/bot/ktor/TelegramBotPipelinesHandler {
public static final field Companion Ldev/inmo/tgbotapi/bot/ktor/middlewares/TelegramBotMiddlewaresPipelinesHandler$Companion; public static final field Companion Ldev/inmo/tgbotapi/bot/ktor/middlewares/TelegramBotMiddlewaresPipelinesHandler$Companion;
public fun <init> ()V
public fun <init> (Ljava/util/List;)V public fun <init> (Ljava/util/List;)V
public synthetic fun <init> (Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun onAfterCallFactoryMakeCall (Ljava/lang/Object;Ldev/inmo/tgbotapi/requests/abstracts/Request;Ldev/inmo/tgbotapi/bot/ktor/KtorCallFactory;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun onAfterCallFactoryMakeCall (Ljava/lang/Object;Ldev/inmo/tgbotapi/requests/abstracts/Request;Ldev/inmo/tgbotapi/bot/ktor/KtorCallFactory;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun onBeforeCallFactoryMakeCall (Ldev/inmo/tgbotapi/requests/abstracts/Request;Ldev/inmo/tgbotapi/bot/ktor/KtorCallFactory;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun onBeforeCallFactoryMakeCall (Ldev/inmo/tgbotapi/requests/abstracts/Request;Ldev/inmo/tgbotapi/bot/ktor/KtorCallFactory;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun onBeforeSearchCallFactory (Ldev/inmo/tgbotapi/requests/abstracts/Request;Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun onBeforeSearchCallFactory (Ldev/inmo/tgbotapi/requests/abstracts/Request;Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
@@ -502,6 +507,13 @@ public final class dev/inmo/tgbotapi/bot/ktor/middlewares/TelegramBotMiddlewares
public final fun build (Lkotlin/jvm/functions/Function1;)Ldev/inmo/tgbotapi/bot/ktor/middlewares/TelegramBotMiddlewaresPipelinesHandler; public final fun build (Lkotlin/jvm/functions/Function1;)Ldev/inmo/tgbotapi/bot/ktor/middlewares/TelegramBotMiddlewaresPipelinesHandler;
} }
public final class dev/inmo/tgbotapi/bot/ktor/middlewares/builtins/ExceptionsThrottlerTelegramBotMiddleware {
public static final field INSTANCE Ldev/inmo/tgbotapi/bot/ktor/middlewares/builtins/ExceptionsThrottlerTelegramBotMiddleware;
public static final field id Ljava/lang/String;
public final fun invoke-HG0u8IE (FJ)Ldev/inmo/tgbotapi/bot/ktor/middlewares/TelegramBotMiddleware;
public static synthetic fun invoke-HG0u8IE$default (Ldev/inmo/tgbotapi/bot/ktor/middlewares/builtins/ExceptionsThrottlerTelegramBotMiddleware;FJILjava/lang/Object;)Ldev/inmo/tgbotapi/bot/ktor/middlewares/TelegramBotMiddleware;
}
public final class dev/inmo/tgbotapi/bot/multiserver/SimpleMultiServerRequestsExecutor : dev/inmo/tgbotapi/bot/RequestsExecutor { public final class dev/inmo/tgbotapi/bot/multiserver/SimpleMultiServerRequestsExecutor : dev/inmo/tgbotapi/bot/RequestsExecutor {
public static final field Companion Ldev/inmo/tgbotapi/bot/multiserver/SimpleMultiServerRequestsExecutor$Companion; public static final field Companion Ldev/inmo/tgbotapi/bot/multiserver/SimpleMultiServerRequestsExecutor$Companion;
public fun <init> (Ljava/util/List;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function0;)V public fun <init> (Ljava/util/List;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function0;)V
@@ -1022,7 +1034,7 @@ public final class dev/inmo/tgbotapi/requests/abstracts/MultipartFile : dev/inmo
public fun equals (Ljava/lang/Object;)Z public fun equals (Ljava/lang/Object;)Z
public fun getFileId ()Ljava/lang/String; public fun getFileId ()Ljava/lang/String;
public final fun getFilename ()Ljava/lang/String; public final fun getFilename ()Ljava/lang/String;
public final fun getInput ()Lio/ktor/utils/io/core/Input; public final fun getInput ()Lkotlinx/io/Source;
public fun hashCode ()I public fun hashCode ()I
public fun toString ()Ljava/lang/String; public fun toString ()Ljava/lang/String;
} }

View File

@@ -2,6 +2,7 @@ package dev.inmo.tgbotapi.bot.ktor
import dev.inmo.kslog.common.KSLog import dev.inmo.kslog.common.KSLog
import dev.inmo.tgbotapi.bot.BaseRequestsExecutor import dev.inmo.tgbotapi.bot.BaseRequestsExecutor
import dev.inmo.tgbotapi.bot.ktor.middlewares.TelegramBotMiddlewaresPipelinesHandler
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
import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.requests.abstracts.Request
@@ -39,7 +40,7 @@ fun KtorRequestsExecutor(
excludeDefaultFactories: Boolean = false, excludeDefaultFactories: Boolean = false,
requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter, requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter,
jsonFormatter: Json = nonstrictJsonFormat, jsonFormatter: Json = nonstrictJsonFormat,
pipelineStepsHolder: TelegramBotPipelinesHandler = TelegramBotPipelinesHandler, pipelineStepsHolder: TelegramBotPipelinesHandler = TelegramBotMiddlewaresPipelinesHandler(),
logger: KSLog = DefaultKTgBotAPIKSLog, logger: KSLog = DefaultKTgBotAPIKSLog,
) = KtorRequestsExecutor( ) = KtorRequestsExecutor(
telegramAPIUrlsKeeper = telegramAPIUrlsKeeper, telegramAPIUrlsKeeper = telegramAPIUrlsKeeper,

View File

@@ -27,7 +27,7 @@ class KtorRequestsExecutorBuilder(
var requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter var requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter
var jsonFormatter: Json = nonstrictJsonFormat var jsonFormatter: Json = nonstrictJsonFormat
var logger: KSLog = DefaultKTgBotAPIKSLog var logger: KSLog = DefaultKTgBotAPIKSLog
var pipelineStepsHolder: TelegramBotPipelinesHandler = TelegramBotPipelinesHandler var pipelineStepsHolder: TelegramBotPipelinesHandler = TelegramBotMiddlewaresPipelinesHandler()
fun includeMiddlewares(block: TelegramBotMiddlewaresPipelinesHandler.Builder.() -> Unit) { fun includeMiddlewares(block: TelegramBotMiddlewaresPipelinesHandler.Builder.() -> Unit) {
pipelineStepsHolder = TelegramBotMiddlewaresPipelinesHandler.build(block) pipelineStepsHolder = TelegramBotMiddlewaresPipelinesHandler.build(block)

View File

@@ -47,7 +47,7 @@ class DefaultKtorRequestsExecutor internal constructor(
} }
override suspend fun <T : Any> execute(request: Request<T>): T { override suspend fun <T : Any> execute(request: Request<T>): T {
return runCatchingSafely { return runCatching {
logger.v { "Start request $request" } logger.v { "Start request $request" }
pipelineStepsHolder.onBeforeSearchCallFactory(request, callsFactories) pipelineStepsHolder.onBeforeSearchCallFactory(request, callsFactories)
requestsLimiter.limit(request) { requestsLimiter.limit(request) {

View File

@@ -8,9 +8,7 @@ import dev.inmo.tgbotapi.utils.ByteReadChannelAllocator
import dev.inmo.tgbotapi.utils.RiskFeature import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.call.receive
import io.ktor.client.request.get import io.ktor.client.request.get
import io.ktor.client.statement.HttpStatement
import io.ktor.client.statement.bodyAsChannel import io.ktor.client.statement.bodyAsChannel
import io.ktor.utils.io.* import io.ktor.utils.io.*
import kotlinx.coroutines.* import kotlinx.coroutines.*

View File

@@ -6,9 +6,9 @@ import dev.inmo.tgbotapi.requests.DownloadFile
import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.utils.RiskFeature import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import io.ktor.client.HttpClient import io.ktor.client.*
import io.ktor.client.request.get import io.ktor.client.request.*
import io.ktor.client.statement.readBytes import io.ktor.client.statement.*
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
@RiskFeature @RiskFeature
@@ -17,13 +17,13 @@ object DownloadFileRequestCallFactory : KtorCallFactory {
client: HttpClient, client: HttpClient,
urlsKeeper: TelegramAPIUrlsKeeper, urlsKeeper: TelegramAPIUrlsKeeper,
request: Request<T>, request: Request<T>,
jsonFormatter: Json jsonFormatter: Json,
): T? = (request as? DownloadFile) ?.let { ): T? = (request as? DownloadFile)?.let {
val fullUrl = urlsKeeper.createFileLinkUrl(it.filePath) val fullUrl = urlsKeeper.createFileLinkUrl(it.filePath)
safely { safely {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
client.get(fullUrl).readBytes() as T // always ByteArray client.get(fullUrl).readRawBytes() as T // always ByteArray
} }
} }
} }

View File

@@ -38,7 +38,7 @@ internal expect inline fun platformClientCopy(client: HttpClient): HttpClient
* @param requestExecutorsCount Amount of [DefaultKtorRequestsExecutor] which will be created and used under the * @param requestExecutorsCount Amount of [DefaultKtorRequestsExecutor] which will be created and used under the
* hood * hood
*/ */
class MultipleClientKtorRequestsExecutor ( class MultipleClientKtorRequestsExecutor(
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper, telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper,
callsFactories: List<KtorCallFactory>, callsFactories: List<KtorCallFactory>,
excludeDefaultFactories: Boolean, excludeDefaultFactories: Boolean,
@@ -47,7 +47,7 @@ class MultipleClientKtorRequestsExecutor (
pipelineStepsHolder: TelegramBotPipelinesHandler, pipelineStepsHolder: TelegramBotPipelinesHandler,
requestExecutorsCount: Int, requestExecutorsCount: Int,
logger: KSLog, logger: KSLog,
clientFactory: () -> HttpClient clientFactory: () -> HttpClient,
) : BaseRequestsExecutor(telegramAPIUrlsKeeper) { ) : BaseRequestsExecutor(telegramAPIUrlsKeeper) {
private val requestExecutors = (0 until requestExecutorsCount).map { private val requestExecutors = (0 until requestExecutorsCount).map {
DefaultKtorRequestsExecutor( DefaultKtorRequestsExecutor(
@@ -66,7 +66,7 @@ class MultipleClientKtorRequestsExecutor (
private val clientAllocationMutex = Mutex() private val clientAllocationMutex = Mutex()
private val takerFlow = freeClients.mapNotNull { private val takerFlow = freeClients.mapNotNull {
clientAllocationMutex.withLock { clientAllocationMutex.withLock {
freeClients.value.firstOrNull() ?.also { freeClients.value.firstOrNull()?.also {
freeClients.value -= it freeClients.value -= it
} ?: return@mapNotNull null } ?: return@mapNotNull null
} }
@@ -81,7 +81,7 @@ class MultipleClientKtorRequestsExecutor (
jsonFormatter: Json, jsonFormatter: Json,
pipelineStepsHolder: TelegramBotPipelinesHandler, pipelineStepsHolder: TelegramBotPipelinesHandler,
logger: KSLog, logger: KSLog,
diff: Unit diff: Unit,
) : this( ) : this(
telegramAPIUrlsKeeper, telegramAPIUrlsKeeper,
callsFactories, callsFactories,
@@ -89,7 +89,7 @@ class MultipleClientKtorRequestsExecutor (
requestsLimiter, requestsLimiter,
jsonFormatter, jsonFormatter,
pipelineStepsHolder, pipelineStepsHolder,
client.engineConfig.threadsCount, requestExecutorsCount = 4, // default threads count; configurable through dispatcher property
logger, logger,
{ platformClientCopy(client) } { platformClientCopy(client) }
) )

View File

@@ -1,5 +1,6 @@
package dev.inmo.tgbotapi.bot.ktor.middlewares package dev.inmo.tgbotapi.bot.ktor.middlewares
import com.benasher44.uuid.uuid4
import dev.inmo.micro_utils.common.Warning import dev.inmo.micro_utils.common.Warning
import dev.inmo.tgbotapi.bot.ktor.KtorCallFactory import dev.inmo.tgbotapi.bot.ktor.KtorCallFactory
import dev.inmo.tgbotapi.bot.ktor.TelegramBotPipelinesHandler import dev.inmo.tgbotapi.bot.ktor.TelegramBotPipelinesHandler
@@ -22,14 +23,15 @@ import dev.inmo.tgbotapi.requests.abstracts.Request
* Non-null result of lambda will be used as the result of request handling * Non-null result of lambda will be used as the result of request handling
*/ */
@Warning("This API is experimental and subject of changes") @Warning("This API is experimental and subject of changes")
class TelegramBotMiddleware( open class TelegramBotMiddleware(
internal val onRequestException: (suspend (request: Request<*>, t: Throwable?) -> Any?)? = null, internal val onRequestException: (suspend (request: Request<*>, t: Throwable?) -> Any?)? = null,
internal val onBeforeSearchCallFactory: (suspend (request: Request<*>, callsFactories: List<KtorCallFactory>) -> Unit)? = null, internal val onBeforeSearchCallFactory: (suspend (request: Request<*>, callsFactories: List<KtorCallFactory>) -> Unit)? = null,
internal val onBeforeCallFactoryMakeCall: (suspend (request: Request<*>, potentialFactory: KtorCallFactory) -> Unit)? = null, internal val onBeforeCallFactoryMakeCall: (suspend (request: Request<*>, potentialFactory: KtorCallFactory) -> Unit)? = null,
internal val onAfterCallFactoryMakeCall: (suspend (result: Any?, request: Request<*>, potentialFactory: KtorCallFactory) -> Any?)? = null, internal val onAfterCallFactoryMakeCall: (suspend (result: Any?, request: Request<*>, potentialFactory: KtorCallFactory) -> Any?)? = null,
internal val onRequestResultPresented: (suspend (result: Any?, request: Request<*>, resultCallFactory: KtorCallFactory, callsFactories: List<KtorCallFactory>) -> Any?)? = null, internal val onRequestResultPresented: (suspend (result: Any, request: Request<*>, resultCallFactory: KtorCallFactory, callsFactories: List<KtorCallFactory>) -> Any?)? = null,
internal val onRequestResultAbsent: (suspend (request: Request<*>, callsFactories: List<KtorCallFactory>) -> Any?)? = null, internal val onRequestResultAbsent: (suspend (request: Request<*>, callsFactories: List<KtorCallFactory>) -> Any?)? = null,
internal val onRequestReturnResult: (suspend (result: Result<*>, request: Request<*>, callsFactories: List<KtorCallFactory>) -> Result<Any?>?)? = null, internal val onRequestReturnResult: (suspend (result: Result<*>, request: Request<*>, callsFactories: List<KtorCallFactory>) -> Result<Any?>?)? = null,
val id: String = uuid4().toString()
) : TelegramBotPipelinesHandler { ) : TelegramBotPipelinesHandler {
object ResultAbsence : Throwable() object ResultAbsence : Throwable()
override suspend fun <T : Any> onRequestException(request: Request<T>, t: Throwable): T? { override suspend fun <T : Any> onRequestException(request: Request<T>, t: Throwable): T? {

View File

@@ -1,5 +1,6 @@
package dev.inmo.tgbotapi.bot.ktor.middlewares package dev.inmo.tgbotapi.bot.ktor.middlewares
import com.benasher44.uuid.uuid4
import dev.inmo.micro_utils.common.Warning import dev.inmo.micro_utils.common.Warning
import dev.inmo.tgbotapi.bot.ktor.KtorCallFactory import dev.inmo.tgbotapi.bot.ktor.KtorCallFactory
import dev.inmo.tgbotapi.bot.ktor.TelegramBotPipelinesHandler import dev.inmo.tgbotapi.bot.ktor.TelegramBotPipelinesHandler
@@ -11,9 +12,10 @@ class TelegramBotMiddlewareBuilder {
var onBeforeSearchCallFactory: (suspend (request: Request<*>, callsFactories: List<KtorCallFactory>) -> Unit)? = null var onBeforeSearchCallFactory: (suspend (request: Request<*>, callsFactories: List<KtorCallFactory>) -> Unit)? = null
var onBeforeCallFactoryMakeCall: (suspend (request: Request<*>, potentialFactory: KtorCallFactory) -> Unit)? = null var onBeforeCallFactoryMakeCall: (suspend (request: Request<*>, potentialFactory: KtorCallFactory) -> Unit)? = null
var onAfterCallFactoryMakeCall: (suspend (result: Any?, request: Request<*>, potentialFactory: KtorCallFactory) -> Any?)? = null var onAfterCallFactoryMakeCall: (suspend (result: Any?, request: Request<*>, potentialFactory: KtorCallFactory) -> Any?)? = null
var onRequestResultPresented: (suspend (result: Any?, request: Request<*>, resultCallFactory: KtorCallFactory, callsFactories: List<KtorCallFactory>) -> Any?)? = null var onRequestResultPresented: (suspend (result: Any, request: Request<*>, resultCallFactory: KtorCallFactory, callsFactories: List<KtorCallFactory>) -> Any?)? = null
var onRequestResultAbsent: (suspend (request: Request<*>, callsFactories: List<KtorCallFactory>) -> Any?)? = null var onRequestResultAbsent: (suspend (request: Request<*>, callsFactories: List<KtorCallFactory>) -> Any?)? = null
var onRequestReturnResult: (suspend (result: Result<*>, request: Request<*>, callsFactories: List<KtorCallFactory>) -> Result<Any?>?)? = null var onRequestReturnResult: (suspend (result: Result<*>, request: Request<*>, callsFactories: List<KtorCallFactory>) -> Result<Any?>?)? = null
var id: String = uuid4().toString()
/** /**
* Useful way to set [onRequestException] * Useful way to set [onRequestException]
@@ -42,7 +44,7 @@ class TelegramBotMiddlewareBuilder {
/** /**
* Useful way to set [onRequestResultPresented] * Useful way to set [onRequestResultPresented]
*/ */
fun doOnRequestResultPresented(block: suspend (result: Any?, request: Request<*>, resultCallFactory: KtorCallFactory, callsFactories: List<KtorCallFactory>) -> Any?) { fun doOnRequestResultPresented(block: suspend (result: Any, request: Request<*>, resultCallFactory: KtorCallFactory, callsFactories: List<KtorCallFactory>) -> Any?) {
onRequestResultPresented = block onRequestResultPresented = block
} }
/** /**
@@ -67,7 +69,8 @@ class TelegramBotMiddlewareBuilder {
onAfterCallFactoryMakeCall = onAfterCallFactoryMakeCall, onAfterCallFactoryMakeCall = onAfterCallFactoryMakeCall,
onRequestResultPresented = onRequestResultPresented, onRequestResultPresented = onRequestResultPresented,
onRequestResultAbsent = onRequestResultAbsent, onRequestResultAbsent = onRequestResultAbsent,
onRequestReturnResult = onRequestReturnResult onRequestReturnResult = onRequestReturnResult,
id = id
) )
} }
@@ -82,6 +85,7 @@ class TelegramBotMiddlewareBuilder {
onRequestResultPresented = middleware.onRequestResultPresented onRequestResultPresented = middleware.onRequestResultPresented
onRequestResultAbsent = middleware.onRequestResultAbsent onRequestResultAbsent = middleware.onRequestResultAbsent
onRequestReturnResult = middleware.onRequestReturnResult onRequestReturnResult = middleware.onRequestReturnResult
id = middleware.id
additionalSetup() additionalSetup()
}.build() }.build()
} }

View File

@@ -3,11 +3,12 @@ package dev.inmo.tgbotapi.bot.ktor.middlewares
import dev.inmo.micro_utils.common.Warning import dev.inmo.micro_utils.common.Warning
import dev.inmo.tgbotapi.bot.ktor.KtorCallFactory import dev.inmo.tgbotapi.bot.ktor.KtorCallFactory
import dev.inmo.tgbotapi.bot.ktor.TelegramBotPipelinesHandler import dev.inmo.tgbotapi.bot.ktor.TelegramBotPipelinesHandler
import dev.inmo.tgbotapi.bot.ktor.middlewares.builtins.ExceptionsThrottlerTelegramBotMiddleware
import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.requests.abstracts.Request
@Warning("This API is experimental and subject of changes") @Warning("This API is experimental and subject of changes")
class TelegramBotMiddlewaresPipelinesHandler( class TelegramBotMiddlewaresPipelinesHandler(
private val middlewares: List<TelegramBotMiddleware> private val middlewares: List<TelegramBotMiddleware> = emptyList()
) : TelegramBotPipelinesHandler { ) : TelegramBotPipelinesHandler {
override suspend fun <T : Any> onRequestException(request: Request<T>, t: Throwable): T? { override suspend fun <T : Any> onRequestException(request: Request<T>, t: Throwable): T? {
return middlewares.firstNotNullOfOrNull { return middlewares.firstNotNullOfOrNull {
@@ -72,6 +73,7 @@ class TelegramBotMiddlewaresPipelinesHandler(
@Warning("This API is experimental and subject of changes") @Warning("This API is experimental and subject of changes")
class Builder { class Builder {
@Warning("This API is experimental and subject of changes")
val middlewares = mutableListOf<TelegramBotMiddleware>() val middlewares = mutableListOf<TelegramBotMiddleware>()
@Warning("This API is experimental and subject of changes") @Warning("This API is experimental and subject of changes")

View File

@@ -0,0 +1,59 @@
package dev.inmo.tgbotapi.bot.ktor.middlewares.builtins
import dev.inmo.tgbotapi.bot.ktor.middlewares.TelegramBotMiddleware
import dev.inmo.tgbotapi.requests.abstracts.Request
import korlibs.time.milliseconds
import kotlinx.coroutines.delay
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlin.reflect.KClass
import kotlin.time.Duration
/**
* @see invoke
*/
object ExceptionsThrottlerTelegramBotMiddleware {
const val id: String = "ExceptionsThrottlerTelegramBotMiddleware"
/**
* Creates [TelegramBotMiddleware] and configures it with next parameters:
*
* * [TelegramBotMiddleware.onRequestException] will throttle after exception if exception has happened before
* * [TelegramBotMiddleware.onRequestReturnResult] will clear state of all exceptions happened with the [Request] if its
* handling has been completed successfully
*/
operator fun invoke(
exceptionDurationMultiplier: Float = 2f,
initialExceptionDuration: Duration = 125.milliseconds,
): TelegramBotMiddleware = TelegramBotMiddleware.build {
val exceptionsTimeouts = mutableMapOf<KClass<*>, Duration>()
val latestExceptionsRequestsTypes = mutableMapOf<KClass<*>, MutableSet<KClass<*>>>()
val mutex = Mutex()
onRequestException = onRequestException@{ request, t ->
t ?: return@onRequestException null
val kclass = t::class
val toSleep = mutex.withLock {
val latestDuration = exceptionsTimeouts[kclass]
exceptionsTimeouts[kclass] = latestDuration ?.times(exceptionDurationMultiplier.toDouble()) ?: initialExceptionDuration
latestExceptionsRequestsTypes.getOrPut(request::class) { mutableSetOf() }.add(kclass)
latestDuration
}
toSleep ?.let {
delay(it)
}
null
}
onRequestReturnResult = onRequestReturnResult@{ result, request, _ ->
if (result.isSuccess) {
mutex.withLock {
val exceptionKClass = latestExceptionsRequestsTypes.remove(request::class) ?: return@withLock
exceptionKClass.forEach {
exceptionsTimeouts.remove(it)
}
}
}
null
}
id = ExceptionsThrottlerTelegramBotMiddleware.id
}
}

View File

@@ -1,8 +1,6 @@
package dev.inmo.tgbotapi.utils package dev.inmo.tgbotapi.utils
import io.ktor.util.toByteArray import io.ktor.utils.io.*
import io.ktor.utils.io.ByteReadChannel import io.ktor.utils.io.core.*
import io.ktor.utils.io.core.ByteReadPacket
import io.ktor.utils.io.core.Input
actual suspend fun ByteReadChannel.asInput(): Input = ByteReadPacket(toByteArray()) actual suspend fun ByteReadChannel.asInput(): Input = ByteReadPacket(toByteArray())

View File

@@ -3541,10 +3541,10 @@ public final class dev/inmo/tgbotapi/extensions/utils/updates/retrieving/Webhook
public static synthetic fun includeWebhookHandlingInRoute$default (Lio/ktor/server/routing/Route;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;JLkotlin/jvm/functions/Function2;ILjava/lang/Object;)V public static synthetic fun includeWebhookHandlingInRoute$default (Lio/ktor/server/routing/Route;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;JLkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
public static final fun includeWebhookHandlingInRouteWithFlows (Lio/ktor/server/routing/Route;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;JLkotlin/jvm/functions/Function1;)V public static final fun includeWebhookHandlingInRouteWithFlows (Lio/ktor/server/routing/Route;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;JLkotlin/jvm/functions/Function1;)V
public static synthetic fun includeWebhookHandlingInRouteWithFlows$default (Lio/ktor/server/routing/Route;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;JLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V public static synthetic fun includeWebhookHandlingInRouteWithFlows$default (Lio/ktor/server/routing/Route;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;JLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
public static final fun setWebhookInfoAndStartListenWebhooks (Ldev/inmo/tgbotapi/bot/RequestsExecutor;ILio/ktor/server/engine/ApplicationEngineFactory;Ldev/inmo/tgbotapi/requests/webhook/SetWebhookRequest;Lkotlin/jvm/functions/Function2;Ljava/lang/String;Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/webhook/WebhookPrivateKeyConfig;Lkotlinx/coroutines/CoroutineScope;JLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun setWebhookInfoAndStartListenWebhooks (Ldev/inmo/tgbotapi/bot/RequestsExecutor;ILio/ktor/server/engine/ApplicationEngineFactory;Ldev/inmo/tgbotapi/requests/webhook/SetWebhookRequest;Lkotlin/jvm/functions/Function2;Ljava/lang/String;Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/webhook/WebhookPrivateKeyConfig;Lkotlinx/coroutines/CoroutineScope;JLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun setWebhookInfoAndStartListenWebhooks$default (Ldev/inmo/tgbotapi/bot/RequestsExecutor;ILio/ktor/server/engine/ApplicationEngineFactory;Ldev/inmo/tgbotapi/requests/webhook/SetWebhookRequest;Lkotlin/jvm/functions/Function2;Ljava/lang/String;Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/webhook/WebhookPrivateKeyConfig;Lkotlinx/coroutines/CoroutineScope;JLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; public static synthetic fun setWebhookInfoAndStartListenWebhooks$default (Ldev/inmo/tgbotapi/bot/RequestsExecutor;ILio/ktor/server/engine/ApplicationEngineFactory;Ldev/inmo/tgbotapi/requests/webhook/SetWebhookRequest;Lkotlin/jvm/functions/Function2;Ljava/lang/String;Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/webhook/WebhookPrivateKeyConfig;Lkotlinx/coroutines/CoroutineScope;JLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
public static final fun startListenWebhooks (ILio/ktor/server/engine/ApplicationEngineFactory;Lkotlin/jvm/functions/Function2;Ljava/lang/String;Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/webhook/WebhookPrivateKeyConfig;Lkotlinx/coroutines/CoroutineScope;JLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lio/ktor/server/engine/ApplicationEngine; public static final fun startListenWebhooks (ILio/ktor/server/engine/ApplicationEngineFactory;Lkotlin/jvm/functions/Function2;Ljava/lang/String;Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/webhook/WebhookPrivateKeyConfig;Lkotlinx/coroutines/CoroutineScope;JLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lio/ktor/server/engine/EmbeddedServer;
public static synthetic fun startListenWebhooks$default (ILio/ktor/server/engine/ApplicationEngineFactory;Lkotlin/jvm/functions/Function2;Ljava/lang/String;Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/webhook/WebhookPrivateKeyConfig;Lkotlinx/coroutines/CoroutineScope;JLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lio/ktor/server/engine/ApplicationEngine; public static synthetic fun startListenWebhooks$default (ILio/ktor/server/engine/ApplicationEngineFactory;Lkotlin/jvm/functions/Function2;Ljava/lang/String;Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/webhook/WebhookPrivateKeyConfig;Lkotlinx/coroutines/CoroutineScope;JLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lio/ktor/server/engine/EmbeddedServer;
} }
public final class dev/inmo/tgbotapi/types/files/PathedFileAsStreamKt { public final class dev/inmo/tgbotapi/types/files/PathedFileAsStreamKt {

View File

@@ -1,19 +1,21 @@
package dev.inmo.tgbotapi.extensions.utils.updates.retrieving package dev.inmo.tgbotapi.extensions.utils.updates.retrieving
import dev.inmo.micro_utils.coroutines.* import dev.inmo.micro_utils.coroutines.ExceptionHandler
import dev.inmo.micro_utils.coroutines.runCatchingSafely
import dev.inmo.tgbotapi.bot.RequestsExecutor import dev.inmo.tgbotapi.bot.RequestsExecutor
import dev.inmo.tgbotapi.extensions.utils.nonstrictJsonFormat import dev.inmo.tgbotapi.extensions.utils.nonstrictJsonFormat
import dev.inmo.tgbotapi.extensions.utils.updates.flowsUpdatesFilter import dev.inmo.tgbotapi.extensions.utils.updates.flowsUpdatesFilter
import dev.inmo.tgbotapi.requests.webhook.SetWebhookRequest import dev.inmo.tgbotapi.requests.webhook.SetWebhookRequest
import dev.inmo.tgbotapi.types.update.abstracts.Update import dev.inmo.tgbotapi.types.update.abstracts.Update
import dev.inmo.tgbotapi.types.update.abstracts.UpdateDeserializationStrategy import dev.inmo.tgbotapi.types.update.abstracts.UpdateDeserializationStrategy
import dev.inmo.tgbotapi.updateshandlers.* import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
import dev.inmo.tgbotapi.updateshandlers.UpdateReceiver
import dev.inmo.tgbotapi.updateshandlers.UpdatesFilter
import dev.inmo.tgbotapi.updateshandlers.webhook.WebhookPrivateKeyConfig import dev.inmo.tgbotapi.updateshandlers.webhook.WebhookPrivateKeyConfig
import io.ktor.http.HttpStatusCode import io.ktor.http.*
import io.ktor.server.application.call
import io.ktor.server.engine.* import io.ktor.server.engine.*
import io.ktor.server.request.receiveText import io.ktor.server.request.*
import io.ktor.server.response.respond import io.ktor.server.response.*
import io.ktor.server.routing.* import io.ktor.server.routing.*
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.asCoroutineDispatcher
@@ -38,7 +40,7 @@ fun Route.includeWebhookHandlingInRoute(
scope: CoroutineScope, scope: CoroutineScope,
exceptionsHandler: ExceptionHandler<Unit>? = null, exceptionsHandler: ExceptionHandler<Unit>? = null,
mediaGroupsDebounceTimeMillis: Long = 1000L, mediaGroupsDebounceTimeMillis: Long = 1000L,
block: UpdateReceiver<Update> block: UpdateReceiver<Update>,
) { ) {
val transformer = scope.updateHandlerWithMediaGroupsAdaptation(block, mediaGroupsDebounceTimeMillis) val transformer = scope.updateHandlerWithMediaGroupsAdaptation(block, mediaGroupsDebounceTimeMillis)
post { post {
@@ -55,7 +57,7 @@ fun Route.includeWebhookHandlingInRoute(
call.respond(HttpStatusCode.InternalServerError) call.respond(HttpStatusCode.InternalServerError)
}.getOrThrow() }.getOrThrow()
} catch (e: Throwable) { } catch (e: Throwable) {
exceptionsHandler ?.invoke(e) exceptionsHandler?.invoke(e)
} }
} }
} }
@@ -69,7 +71,7 @@ fun Route.includeWebhookHandlingInRouteWithFlows(
scope: CoroutineScope, scope: CoroutineScope,
exceptionsHandler: ExceptionHandler<Unit>? = null, exceptionsHandler: ExceptionHandler<Unit>? = null,
mediaGroupsDebounceTimeMillis: Long = 1000L, mediaGroupsDebounceTimeMillis: Long = 1000L,
block: FlowsUpdatesFilter.() -> Unit block: FlowsUpdatesFilter.() -> Unit,
) = includeWebhookHandlingInRoute( ) = includeWebhookHandlingInRoute(
scope, scope,
exceptionsHandler, exceptionsHandler,
@@ -92,50 +94,57 @@ fun Route.includeWebhookHandlingInRouteWithFlows(
* @see UpdatesFilter * @see UpdatesFilter
* @see UpdatesFilter.asUpdateReceiver * @see UpdatesFilter.asUpdateReceiver
*/ */
fun startListenWebhooks( fun <TEngine : ApplicationEngine, TConfiguration : ApplicationEngine.Configuration> startListenWebhooks(
listenPort: Int, listenPort: Int,
engineFactory: ApplicationEngineFactory<*, *>, engineFactory: ApplicationEngineFactory<TEngine, TConfiguration>,
exceptionsHandler: ExceptionHandler<Unit>, exceptionsHandler: ExceptionHandler<Unit>,
listenHost: String = "0.0.0.0", listenHost: String = "0.0.0.0",
listenRoute: String? = null, listenRoute: String? = null,
privateKeyConfig: WebhookPrivateKeyConfig? = null, privateKeyConfig: WebhookPrivateKeyConfig? = null,
scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()), scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()),
mediaGroupsDebounceTimeMillis: Long = 1000L, mediaGroupsDebounceTimeMillis: Long = 1000L,
additionalApplicationEngineEnvironmentConfigurator: ApplicationEngineEnvironmentBuilder.() -> Unit = {}, additionalApplicationEnvironmentConfigurator: ApplicationEnvironmentBuilder.() -> Unit = {},
block: UpdateReceiver<Update> additionalEngineConfigurator: TConfiguration.() -> Unit = {},
): ApplicationEngine { block: UpdateReceiver<Update>,
val env = applicationEngineEnvironment { ): EmbeddedServer<TEngine, TConfiguration> =
embeddedServer(
module { factory = engineFactory,
routing { environment = applicationEnvironment {
listenRoute ?.also { additionalApplicationEnvironmentConfigurator()
createRouteFromPath(it).includeWebhookHandlingInRoute(scope, exceptionsHandler, mediaGroupsDebounceTimeMillis, block) },
} ?: includeWebhookHandlingInRoute(scope, exceptionsHandler, mediaGroupsDebounceTimeMillis, block) configure = {
} privateKeyConfig?.let {
} sslConnector(
privateKeyConfig.keyStore,
privateKeyConfig ?.let { privateKeyConfig.aliasName,
sslConnector( privateKeyConfig::keyStorePassword,
privateKeyConfig.keyStore, privateKeyConfig::aliasPassword
privateKeyConfig.aliasName, ) {
privateKeyConfig::keyStorePassword, host = listenHost
privateKeyConfig::aliasPassword port = listenPort
) { }
} ?: connector {
host = listenHost host = listenHost
port = listenPort port = listenPort
} }
} ?: connector {
host = listenHost additionalEngineConfigurator()
port = listenPort },
module = {
routing {
listenRoute?.also {
createRouteFromPath(it).includeWebhookHandlingInRoute(
scope,
exceptionsHandler,
mediaGroupsDebounceTimeMillis,
block
)
} ?: includeWebhookHandlingInRoute(scope, exceptionsHandler, mediaGroupsDebounceTimeMillis, block)
}
} }
).also {
additionalApplicationEngineEnvironmentConfigurator()
}
return embeddedServer(engineFactory, env).also {
it.start(false) it.start(false)
} }
}
/** /**
* Setting up ktor server, set webhook info via [SetWebhookRequest] request. * Setting up ktor server, set webhook info via [SetWebhookRequest] request.
@@ -152,9 +161,9 @@ fun startListenWebhooks(
* @see UpdatesFilter.asUpdateReceiver * @see UpdatesFilter.asUpdateReceiver
*/ */
@Suppress("unused") @Suppress("unused")
suspend fun RequestsExecutor.setWebhookInfoAndStartListenWebhooks( suspend fun <TEngine : ApplicationEngine, TConfiguration : ApplicationEngine.Configuration> RequestsExecutor.setWebhookInfoAndStartListenWebhooks(
listenPort: Int, listenPort: Int,
engineFactory: ApplicationEngineFactory<*, *>, engineFactory: ApplicationEngineFactory<TEngine, TConfiguration>,
setWebhookRequest: SetWebhookRequest, setWebhookRequest: SetWebhookRequest,
exceptionsHandler: ExceptionHandler<Unit> = {}, exceptionsHandler: ExceptionHandler<Unit> = {},
listenHost: String = "0.0.0.0", listenHost: String = "0.0.0.0",
@@ -162,11 +171,24 @@ suspend fun RequestsExecutor.setWebhookInfoAndStartListenWebhooks(
privateKeyConfig: WebhookPrivateKeyConfig? = null, privateKeyConfig: WebhookPrivateKeyConfig? = null,
scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()), scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()),
mediaGroupsDebounceTimeMillis: Long = 1000L, mediaGroupsDebounceTimeMillis: Long = 1000L,
additionalApplicationEngineEnvironmentConfigurator: ApplicationEngineEnvironmentBuilder.() -> Unit = {}, additionalApplicationEnvironmentConfigurator: ApplicationEnvironmentBuilder.() -> Unit = {},
block: UpdateReceiver<Update> additionalEngineConfigurator: TConfiguration.() -> Unit = {},
): ApplicationEngine = try { block: UpdateReceiver<Update>,
): EmbeddedServer<TEngine, TConfiguration> = try {
execute(setWebhookRequest) execute(setWebhookRequest)
startListenWebhooks(listenPort, engineFactory, exceptionsHandler, listenHost, listenRoute, privateKeyConfig, scope, mediaGroupsDebounceTimeMillis, additionalApplicationEngineEnvironmentConfigurator, block) startListenWebhooks(
listenPort,
engineFactory,
exceptionsHandler,
listenHost,
listenRoute,
privateKeyConfig,
scope,
mediaGroupsDebounceTimeMillis,
additionalApplicationEnvironmentConfigurator,
additionalEngineConfigurator,
block
)
} catch (e: Exception) { } catch (e: Exception) {
throw e throw e
} }