mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2024-12-22 08:37:12 +00:00
commit
c39e9fc156
2
.github/workflows/packages_publishing.yml
vendored
2
.github/workflows/packages_publishing.yml
vendored
@ -17,7 +17,7 @@ jobs:
|
||||
rm gradle.properties
|
||||
mv gradle.properties.tmp gradle.properties
|
||||
- name: KotlinSymbolProcessing execution
|
||||
run: ./gradlew ksp
|
||||
run: ./gradlew kspCommonMainKotlinMetadata
|
||||
- name: Build
|
||||
run: ./gradlew build
|
||||
- name: API compatibility check
|
||||
|
@ -1,5 +1,11 @@
|
||||
# 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))**
|
||||
|
||||
## 18.2.3
|
||||
|
||||
* `Core`:
|
||||
|
@ -6,4 +6,4 @@ kotlin.incremental=true
|
||||
kotlin.incremental.js=true
|
||||
|
||||
library_group=dev.inmo
|
||||
library_version=18.2.3
|
||||
library_version=19.0.0
|
||||
|
@ -8,12 +8,12 @@ javax-activation = "1.1.1"
|
||||
|
||||
korlibs = "5.4.0"
|
||||
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"
|
||||
|
||||
microutils = "0.22.7"
|
||||
microutils = "0.23.0"
|
||||
kslog = "1.3.6"
|
||||
|
||||
versions = "0.51.0"
|
||||
|
@ -1034,7 +1034,7 @@ public final class dev/inmo/tgbotapi/requests/abstracts/MultipartFile : dev/inmo
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public fun getFileId ()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 toString ()Ljava/lang/String;
|
||||
}
|
||||
|
@ -8,9 +8,7 @@ import dev.inmo.tgbotapi.utils.ByteReadChannelAllocator
|
||||
import dev.inmo.tgbotapi.utils.RiskFeature
|
||||
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.call.receive
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.statement.HttpStatement
|
||||
import io.ktor.client.statement.bodyAsChannel
|
||||
import io.ktor.utils.io.*
|
||||
import kotlinx.coroutines.*
|
||||
|
@ -6,9 +6,9 @@ import dev.inmo.tgbotapi.requests.DownloadFile
|
||||
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||
import dev.inmo.tgbotapi.utils.RiskFeature
|
||||
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.statement.readBytes
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.client.statement.*
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
@RiskFeature
|
||||
@ -17,13 +17,13 @@ object DownloadFileRequestCallFactory : KtorCallFactory {
|
||||
client: HttpClient,
|
||||
urlsKeeper: TelegramAPIUrlsKeeper,
|
||||
request: Request<T>,
|
||||
jsonFormatter: Json
|
||||
): T? = (request as? DownloadFile) ?.let {
|
||||
jsonFormatter: Json,
|
||||
): T? = (request as? DownloadFile)?.let {
|
||||
val fullUrl = urlsKeeper.createFileLinkUrl(it.filePath)
|
||||
|
||||
safely {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
client.get(fullUrl).readBytes() as T // always ByteArray
|
||||
client.get(fullUrl).readRawBytes() as T // always ByteArray
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
* hood
|
||||
*/
|
||||
class MultipleClientKtorRequestsExecutor (
|
||||
class MultipleClientKtorRequestsExecutor(
|
||||
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper,
|
||||
callsFactories: List<KtorCallFactory>,
|
||||
excludeDefaultFactories: Boolean,
|
||||
@ -47,7 +47,7 @@ class MultipleClientKtorRequestsExecutor (
|
||||
pipelineStepsHolder: TelegramBotPipelinesHandler,
|
||||
requestExecutorsCount: Int,
|
||||
logger: KSLog,
|
||||
clientFactory: () -> HttpClient
|
||||
clientFactory: () -> HttpClient,
|
||||
) : BaseRequestsExecutor(telegramAPIUrlsKeeper) {
|
||||
private val requestExecutors = (0 until requestExecutorsCount).map {
|
||||
DefaultKtorRequestsExecutor(
|
||||
@ -66,7 +66,7 @@ class MultipleClientKtorRequestsExecutor (
|
||||
private val clientAllocationMutex = Mutex()
|
||||
private val takerFlow = freeClients.mapNotNull {
|
||||
clientAllocationMutex.withLock {
|
||||
freeClients.value.firstOrNull() ?.also {
|
||||
freeClients.value.firstOrNull()?.also {
|
||||
freeClients.value -= it
|
||||
} ?: return@mapNotNull null
|
||||
}
|
||||
@ -81,7 +81,7 @@ class MultipleClientKtorRequestsExecutor (
|
||||
jsonFormatter: Json,
|
||||
pipelineStepsHolder: TelegramBotPipelinesHandler,
|
||||
logger: KSLog,
|
||||
diff: Unit
|
||||
diff: Unit,
|
||||
) : this(
|
||||
telegramAPIUrlsKeeper,
|
||||
callsFactories,
|
||||
@ -89,7 +89,7 @@ class MultipleClientKtorRequestsExecutor (
|
||||
requestsLimiter,
|
||||
jsonFormatter,
|
||||
pipelineStepsHolder,
|
||||
client.engineConfig.threadsCount,
|
||||
requestExecutorsCount = 4, // default threads count; configurable through dispatcher property
|
||||
logger,
|
||||
{ platformClientCopy(client) }
|
||||
)
|
||||
|
@ -1,8 +1,6 @@
|
||||
package dev.inmo.tgbotapi.utils
|
||||
|
||||
import io.ktor.util.toByteArray
|
||||
import io.ktor.utils.io.ByteReadChannel
|
||||
import io.ktor.utils.io.core.ByteReadPacket
|
||||
import io.ktor.utils.io.core.Input
|
||||
import io.ktor.utils.io.*
|
||||
import io.ktor.utils.io.core.*
|
||||
|
||||
actual suspend fun ByteReadChannel.asInput(): Input = ByteReadPacket(toByteArray())
|
||||
|
@ -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 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 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 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 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 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 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/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/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/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lio/ktor/server/engine/EmbeddedServer;
|
||||
}
|
||||
|
||||
public final class dev/inmo/tgbotapi/types/files/PathedFileAsStreamKt {
|
||||
|
@ -1,19 +1,21 @@
|
||||
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.extensions.utils.nonstrictJsonFormat
|
||||
import dev.inmo.tgbotapi.extensions.utils.updates.flowsUpdatesFilter
|
||||
import dev.inmo.tgbotapi.requests.webhook.SetWebhookRequest
|
||||
import dev.inmo.tgbotapi.types.update.abstracts.Update
|
||||
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 io.ktor.http.HttpStatusCode
|
||||
import io.ktor.server.application.call
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.engine.*
|
||||
import io.ktor.server.request.receiveText
|
||||
import io.ktor.server.response.respond
|
||||
import io.ktor.server.request.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.asCoroutineDispatcher
|
||||
@ -38,7 +40,7 @@ fun Route.includeWebhookHandlingInRoute(
|
||||
scope: CoroutineScope,
|
||||
exceptionsHandler: ExceptionHandler<Unit>? = null,
|
||||
mediaGroupsDebounceTimeMillis: Long = 1000L,
|
||||
block: UpdateReceiver<Update>
|
||||
block: UpdateReceiver<Update>,
|
||||
) {
|
||||
val transformer = scope.updateHandlerWithMediaGroupsAdaptation(block, mediaGroupsDebounceTimeMillis)
|
||||
post {
|
||||
@ -55,7 +57,7 @@ fun Route.includeWebhookHandlingInRoute(
|
||||
call.respond(HttpStatusCode.InternalServerError)
|
||||
}.getOrThrow()
|
||||
} catch (e: Throwable) {
|
||||
exceptionsHandler ?.invoke(e)
|
||||
exceptionsHandler?.invoke(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -69,7 +71,7 @@ fun Route.includeWebhookHandlingInRouteWithFlows(
|
||||
scope: CoroutineScope,
|
||||
exceptionsHandler: ExceptionHandler<Unit>? = null,
|
||||
mediaGroupsDebounceTimeMillis: Long = 1000L,
|
||||
block: FlowsUpdatesFilter.() -> Unit
|
||||
block: FlowsUpdatesFilter.() -> Unit,
|
||||
) = includeWebhookHandlingInRoute(
|
||||
scope,
|
||||
exceptionsHandler,
|
||||
@ -92,50 +94,57 @@ fun Route.includeWebhookHandlingInRouteWithFlows(
|
||||
* @see UpdatesFilter
|
||||
* @see UpdatesFilter.asUpdateReceiver
|
||||
*/
|
||||
fun startListenWebhooks(
|
||||
fun <TEngine : ApplicationEngine, TConfiguration : ApplicationEngine.Configuration> startListenWebhooks(
|
||||
listenPort: Int,
|
||||
engineFactory: ApplicationEngineFactory<*, *>,
|
||||
engineFactory: ApplicationEngineFactory<TEngine, TConfiguration>,
|
||||
exceptionsHandler: ExceptionHandler<Unit>,
|
||||
listenHost: String = "0.0.0.0",
|
||||
listenRoute: String? = null,
|
||||
privateKeyConfig: WebhookPrivateKeyConfig? = null,
|
||||
scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()),
|
||||
mediaGroupsDebounceTimeMillis: Long = 1000L,
|
||||
additionalApplicationEngineEnvironmentConfigurator: ApplicationEngineEnvironmentBuilder.() -> Unit = {},
|
||||
block: UpdateReceiver<Update>
|
||||
): ApplicationEngine {
|
||||
val env = applicationEngineEnvironment {
|
||||
|
||||
module {
|
||||
routing {
|
||||
listenRoute ?.also {
|
||||
createRouteFromPath(it).includeWebhookHandlingInRoute(scope, exceptionsHandler, mediaGroupsDebounceTimeMillis, block)
|
||||
} ?: includeWebhookHandlingInRoute(scope, exceptionsHandler, mediaGroupsDebounceTimeMillis, block)
|
||||
}
|
||||
}
|
||||
|
||||
privateKeyConfig ?.let {
|
||||
sslConnector(
|
||||
privateKeyConfig.keyStore,
|
||||
privateKeyConfig.aliasName,
|
||||
privateKeyConfig::keyStorePassword,
|
||||
privateKeyConfig::aliasPassword
|
||||
) {
|
||||
additionalApplicationEnvironmentConfigurator: ApplicationEnvironmentBuilder.() -> Unit = {},
|
||||
additionalEngineConfigurator: TConfiguration.() -> Unit = {},
|
||||
block: UpdateReceiver<Update>,
|
||||
): EmbeddedServer<TEngine, TConfiguration> =
|
||||
embeddedServer(
|
||||
factory = engineFactory,
|
||||
environment = applicationEnvironment {
|
||||
additionalApplicationEnvironmentConfigurator()
|
||||
},
|
||||
configure = {
|
||||
privateKeyConfig?.let {
|
||||
sslConnector(
|
||||
privateKeyConfig.keyStore,
|
||||
privateKeyConfig.aliasName,
|
||||
privateKeyConfig::keyStorePassword,
|
||||
privateKeyConfig::aliasPassword
|
||||
) {
|
||||
host = listenHost
|
||||
port = listenPort
|
||||
}
|
||||
} ?: connector {
|
||||
host = listenHost
|
||||
port = listenPort
|
||||
}
|
||||
} ?: connector {
|
||||
host = listenHost
|
||||
port = listenPort
|
||||
|
||||
additionalEngineConfigurator()
|
||||
},
|
||||
module = {
|
||||
routing {
|
||||
listenRoute?.also {
|
||||
createRouteFromPath(it).includeWebhookHandlingInRoute(
|
||||
scope,
|
||||
exceptionsHandler,
|
||||
mediaGroupsDebounceTimeMillis,
|
||||
block
|
||||
)
|
||||
} ?: includeWebhookHandlingInRoute(scope, exceptionsHandler, mediaGroupsDebounceTimeMillis, block)
|
||||
}
|
||||
}
|
||||
|
||||
additionalApplicationEngineEnvironmentConfigurator()
|
||||
}
|
||||
|
||||
return embeddedServer(engineFactory, env).also {
|
||||
).also {
|
||||
it.start(false)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setting up ktor server, set webhook info via [SetWebhookRequest] request.
|
||||
@ -152,9 +161,9 @@ fun startListenWebhooks(
|
||||
* @see UpdatesFilter.asUpdateReceiver
|
||||
*/
|
||||
@Suppress("unused")
|
||||
suspend fun RequestsExecutor.setWebhookInfoAndStartListenWebhooks(
|
||||
suspend fun <TEngine : ApplicationEngine, TConfiguration : ApplicationEngine.Configuration> RequestsExecutor.setWebhookInfoAndStartListenWebhooks(
|
||||
listenPort: Int,
|
||||
engineFactory: ApplicationEngineFactory<*, *>,
|
||||
engineFactory: ApplicationEngineFactory<TEngine, TConfiguration>,
|
||||
setWebhookRequest: SetWebhookRequest,
|
||||
exceptionsHandler: ExceptionHandler<Unit> = {},
|
||||
listenHost: String = "0.0.0.0",
|
||||
@ -162,11 +171,24 @@ suspend fun RequestsExecutor.setWebhookInfoAndStartListenWebhooks(
|
||||
privateKeyConfig: WebhookPrivateKeyConfig? = null,
|
||||
scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()),
|
||||
mediaGroupsDebounceTimeMillis: Long = 1000L,
|
||||
additionalApplicationEngineEnvironmentConfigurator: ApplicationEngineEnvironmentBuilder.() -> Unit = {},
|
||||
block: UpdateReceiver<Update>
|
||||
): ApplicationEngine = try {
|
||||
additionalApplicationEnvironmentConfigurator: ApplicationEnvironmentBuilder.() -> Unit = {},
|
||||
additionalEngineConfigurator: TConfiguration.() -> Unit = {},
|
||||
block: UpdateReceiver<Update>,
|
||||
): EmbeddedServer<TEngine, TConfiguration> = try {
|
||||
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) {
|
||||
throw e
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user