diff --git a/CHANGELOG.md b/CHANGELOG.md index c8057dbdc4..0b4fcd9fc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # TelegramBotAPI changelog +## 27.1.0 + +* `Core`: + * Improve support of local bot api servers files. Next call factories will try to resolve file locally before real call: + * [DownloadFileRequestCallFactory.kt](tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/DownloadFileRequestCallFactory.kt) (for [DownloadFile.kt](tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/DownloadFile.kt) as well) + * [DownloadFileChannelRequestCallFactory.kt](tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/DownloadFileChannelRequestCallFactory.kt) (for [DownloadFileStream.kt](tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/DownloadFileStream.kt) as well) + ## 27.0.0 **THIS UPDATE MAY CONTAIN BREAKING CHANGES. IN CASE OF ANY MIGRATION PROBLEMS FEEL FREE TO ASK IN [OUR CHAT](https://t.me/ktgbotapi_chat)** diff --git a/README.md b/README.md index 1b146b9fb9..3b569135cc 100644 --- a/README.md +++ b/README.md @@ -120,3 +120,20 @@ suspend fun main() { You may find examples in [this project](https://github.com/InsanusMokrassar/TelegramBotAPI-examples). Besides, you are always welcome in our [docs](https://docs.inmo.dev/tgbotapi/index.html) and [chat](https://t.me/InMoTelegramBotAPIChat). + +### Bot API Server Notice + +Under the hood, default bots realizations will try to use links +([PathedFile](tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/files/PathedFile.kt)#filePath) as files each +time you are trying to download file from telegram in any way - via saving to file, use stream or download as byte array. +To let bot correctly download files from bot api server, you must: + +* Run bot api server locally +to proxy requests for files to the server where bot api server has been hosted + * In case of local bot api server (shared one host machine) you must ensure that access to bot api server has been + granted for your bot. For example, [aiogram/telegram-bot-api](https://hub.docker.com/r/aiogram/telegram-bot-api) image + use `101` UID/GID in linux for user and group as owners. So, your bot must run under user included in `101` group + (like `systemd-journal`) or be `101` UID user (like `systemd-resolve`) +* **OR** Use some reverse proxy (like nginx). It will allow you to broadcast your bots files without linux rights problems + * Set [TelegramAPIUrlsKeeper](tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/TelegramAPIUrlsKeeper.kt)#fileLinkUrlMapper + to map urls to let bot execute requests to your nginx proxy \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 913ee32681..7b9ca0f16e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,4 +9,4 @@ kotlin.incremental.js=true ksp.useKSP2=false library_group=dev.inmo -library_version=27.0.0 +library_version=27.1.0 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e5c4f6e862..cc13760bd5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -21,8 +21,8 @@ versions = "0.52.0" github-release-plugin = "2.5.2" dokka = "2.0.0" -validator = "0.17.0" -nmcp = "1.0.1" +validator = "0.18.1" +nmcp = "1.0.2" [libraries] diff --git a/tgbotapi.api/api/tgbotapi.api.api b/tgbotapi.api/api/tgbotapi.api.api index 1e5aeaf681..8b67723584 100644 --- a/tgbotapi.api/api/tgbotapi.api.api +++ b/tgbotapi.api/api/tgbotapi.api.api @@ -15,8 +15,8 @@ public final class dev/inmo/tgbotapi/extensions/api/BotBuilder { } public final class dev/inmo/tgbotapi/extensions/api/BotBuilderKt { - public static final fun buildBot (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; - public static synthetic fun buildBot$default (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; + public static final fun buildBot (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; + public static synthetic fun buildBot$default (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; } public final class dev/inmo/tgbotapi/extensions/api/BotExtensionsKt { @@ -24,17 +24,17 @@ public final class dev/inmo/tgbotapi/extensions/api/BotExtensionsKt { public static final fun telegramBot (Ldev/inmo/tgbotapi/utils/TelegramAPIUrlsKeeper;Lio/ktor/client/engine/HttpClientEngine;Lkotlin/jvm/functions/Function1;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; public static final fun telegramBot (Ldev/inmo/tgbotapi/utils/TelegramAPIUrlsKeeper;Lio/ktor/client/engine/HttpClientEngineFactory;Lkotlin/jvm/functions/Function1;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; public static final fun telegramBot (Ldev/inmo/tgbotapi/utils/TelegramAPIUrlsKeeper;Lkotlin/jvm/functions/Function1;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; - public static final fun telegramBot (Ljava/lang/String;Lio/ktor/client/engine/HttpClientEngine;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; - public static final fun telegramBot (Ljava/lang/String;Lio/ktor/client/engine/HttpClientEngineFactory;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; - public static final fun telegramBot (Ljava/lang/String;Ljava/lang/String;ZLio/ktor/client/HttpClient;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; - public static final fun telegramBot (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; + public static final fun telegramBot (Ljava/lang/String;Lio/ktor/client/engine/HttpClientEngine;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; + public static final fun telegramBot (Ljava/lang/String;Lio/ktor/client/engine/HttpClientEngineFactory;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; + public static final fun telegramBot (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;Lio/ktor/client/HttpClient;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; + public static final fun telegramBot (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; public static synthetic fun telegramBot$default (Ldev/inmo/tgbotapi/utils/TelegramAPIUrlsKeeper;Lio/ktor/client/HttpClient;ILjava/lang/Object;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; public static synthetic fun telegramBot$default (Ldev/inmo/tgbotapi/utils/TelegramAPIUrlsKeeper;Lio/ktor/client/engine/HttpClientEngine;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; public static synthetic fun telegramBot$default (Ldev/inmo/tgbotapi/utils/TelegramAPIUrlsKeeper;Lio/ktor/client/engine/HttpClientEngineFactory;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; - public static synthetic fun telegramBot$default (Ljava/lang/String;Lio/ktor/client/engine/HttpClientEngine;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; - public static synthetic fun telegramBot$default (Ljava/lang/String;Lio/ktor/client/engine/HttpClientEngineFactory;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; - public static synthetic fun telegramBot$default (Ljava/lang/String;Ljava/lang/String;ZLio/ktor/client/HttpClient;ILjava/lang/Object;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; - public static synthetic fun telegramBot$default (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; + public static synthetic fun telegramBot$default (Ljava/lang/String;Lio/ktor/client/engine/HttpClientEngine;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; + public static synthetic fun telegramBot$default (Ljava/lang/String;Lio/ktor/client/engine/HttpClientEngineFactory;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; + public static synthetic fun telegramBot$default (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;Lio/ktor/client/HttpClient;ILjava/lang/Object;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; + public static synthetic fun telegramBot$default (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; } public final class dev/inmo/tgbotapi/extensions/api/CloseKt { diff --git a/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/BotBuilder.kt b/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/BotBuilder.kt index e3ed1c1e72..a0ba599c59 100644 --- a/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/BotBuilder.kt +++ b/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/BotBuilder.kt @@ -16,7 +16,7 @@ import io.ktor.client.engine.* public data class BotBuilder internal constructor( var proxy: ProxyConfig? = null, var ktorClientEngineFactory: HttpClientEngineFactory? = null, - var ktorClientConfig: (HttpClientConfig<*>.() -> Unit) ? = null + var ktorClientConfig: (HttpClientConfig<*>.() -> Unit) ? = null, ) { internal fun createHttpClient(): HttpClient = ktorClientEngineFactory ?.let { HttpClient( @@ -42,8 +42,14 @@ public fun buildBot( token: String, apiUrl: String = telegramBotAPIDefaultUrl, testServer: Boolean = false, + fileLinkUrlMapper: TelegramAPIUrlsKeeper.(String) -> String = { "${fileBaseUrl}/$it" }, block: BotBuilder.() -> Unit ): TelegramBot = telegramBot( - TelegramAPIUrlsKeeper(token, testServer, apiUrl), - BotBuilder().apply(block).createHttpClient() + urlsKeeper = TelegramAPIUrlsKeeper( + token = token, + testServer = testServer, + hostUrl = apiUrl, + fileLinkUrlMapper = fileLinkUrlMapper + ), + client = BotBuilder().apply(block).createHttpClient() ) diff --git a/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/BotExtensions.kt b/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/BotExtensions.kt index b53706d43b..c05a7aa8c3 100644 --- a/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/BotExtensions.kt +++ b/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/BotExtensions.kt @@ -63,22 +63,24 @@ public inline fun telegramBot( * Allows to create bot using bot [token], [apiUrl] (for custom api servers) and already prepared [client] */ @Suppress("NOTHING_TO_INLINE") -public inline fun telegramBot( +public fun telegramBot( token: String, apiUrl: String = telegramBotAPIDefaultUrl, testServer: Boolean = false, + fileLinkUrlMapper: TelegramAPIUrlsKeeper.(String) -> String = { "${fileBaseUrl}/$it" }, client: HttpClient = HttpClient() -): TelegramBot = telegramBot(TelegramAPIUrlsKeeper(token, testServer, apiUrl), client) +): TelegramBot = telegramBot(TelegramAPIUrlsKeeper(token, testServer, apiUrl, fileLinkUrlMapper), client) @Suppress("NOTHING_TO_INLINE") -public inline fun telegramBot( +public fun telegramBot( token: String, clientFactory: HttpClientEngineFactory, apiUrl: String = telegramBotAPIDefaultUrl, testServer: Boolean = false, - noinline clientConfig: HttpClientConfig.() -> Unit = {} + fileLinkUrlMapper: TelegramAPIUrlsKeeper.(String) -> String = { "${fileBaseUrl}/$it" }, + clientConfig: HttpClientConfig.() -> Unit = {} ): TelegramBot = telegramBot( - TelegramAPIUrlsKeeper(token, testServer, apiUrl), + TelegramAPIUrlsKeeper(token, testServer, apiUrl, fileLinkUrlMapper), clientFactory, clientConfig ) @@ -87,15 +89,15 @@ public inline fun telegramBot( * Allows to create bot using bot [token] and specify [HttpClientEngine] by passing [clientEngine] param and optionally * configure [HttpClient] using [clientConfig] */ -@Suppress("NOTHING_TO_INLINE") -public inline fun telegramBot( +public fun telegramBot( token: String, clientEngine: HttpClientEngine, apiUrl: String = telegramBotAPIDefaultUrl, testServer: Boolean = false, - noinline clientConfig: HttpClientConfig<*>.() -> Unit = {} + fileLinkUrlMapper: TelegramAPIUrlsKeeper.(String) -> String = { "${fileBaseUrl}/$it" }, + clientConfig: HttpClientConfig<*>.() -> Unit = {} ): TelegramBot = telegramBot( - TelegramAPIUrlsKeeper(token, testServer, apiUrl), + TelegramAPIUrlsKeeper(token, testServer, apiUrl, fileLinkUrlMapper), clientEngine, clientConfig ) @@ -104,13 +106,13 @@ public inline fun telegramBot( * Allows to create bot using bot [token] and [apiUrl] and specify [HttpClientEngine] by configuring [HttpClient] using * [clientConfig] */ -@Suppress("NOTHING_TO_INLINE") -public inline fun telegramBot( +public fun telegramBot( token: String, apiUrl: String = telegramBotAPIDefaultUrl, testServer: Boolean = false, - noinline clientConfig: HttpClientConfig<*>.() -> Unit + fileLinkUrlMapper: TelegramAPIUrlsKeeper.(String) -> String = { "${fileBaseUrl}/$it" }, + clientConfig: HttpClientConfig<*>.() -> Unit ): TelegramBot = telegramBot( - TelegramAPIUrlsKeeper(token, testServer, apiUrl), + TelegramAPIUrlsKeeper(token, testServer, apiUrl, fileLinkUrlMapper), clientConfig ) diff --git a/tgbotapi.behaviour_builder.fsm/api/tgbotapi.behaviour_builder.fsm.api b/tgbotapi.behaviour_builder.fsm/api/tgbotapi.behaviour_builder.fsm.api index c2c92e06e9..38e3f6f5cb 100644 --- a/tgbotapi.behaviour_builder.fsm/api/tgbotapi.behaviour_builder.fsm.api +++ b/tgbotapi.behaviour_builder.fsm/api/tgbotapi.behaviour_builder.fsm.api @@ -128,9 +128,9 @@ public final class dev/inmo/tgbotapi/extensions/behaviour_builder/DefaultBehavio } public final class dev/inmo/tgbotapi/extensions/behaviour_builder/TelegramBotWithFSMKt { - public static final fun telegramBotWithBehaviourAndFSM (Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;ZLkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun telegramBotWithBehaviourAndFSM$default (Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;ZLkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun telegramBotWithBehaviourAndFSMAndStartLongPolling (Ljava/lang/String;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;ZLkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun telegramBotWithBehaviourAndFSMAndStartLongPolling$default (Ljava/lang/String;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;ZLkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static final fun telegramBotWithBehaviourAndFSM (Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;ZLkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun telegramBotWithBehaviourAndFSM$default (Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;ZLkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static final fun telegramBotWithBehaviourAndFSMAndStartLongPolling (Ljava/lang/String;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;ZLkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun telegramBotWithBehaviourAndFSMAndStartLongPolling$default (Ljava/lang/String;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;ZLkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; } diff --git a/tgbotapi.behaviour_builder.fsm/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/TelegramBotWithFSM.kt b/tgbotapi.behaviour_builder.fsm/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/TelegramBotWithFSM.kt index 3681b1210f..2b38cb12e1 100644 --- a/tgbotapi.behaviour_builder.fsm/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/TelegramBotWithFSM.kt +++ b/tgbotapi.behaviour_builder.fsm/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/TelegramBotWithFSM.kt @@ -15,6 +15,7 @@ import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.updateHandlerWithMe import dev.inmo.tgbotapi.types.Seconds import dev.inmo.tgbotapi.types.update.abstracts.Update import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter +import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job @@ -56,11 +57,13 @@ suspend fun telegramBotWithBehaviourAndFSM( mediaGroupsDebounceTimeMillis: Long? = 1000L, subcontextInitialAction: CustomBehaviourContextAndTypeReceiver = {}, stateInitialAction: CustomBehaviourContextAndTypeReceiver, Unit, T> = {}, + fileLinkUrlMapper: TelegramAPIUrlsKeeper.(String) -> String = { "${fileBaseUrl}/$it" }, block: CustomBehaviourContextReceiver, Unit> ): TelegramBot = telegramBot( token, apiUrl, testServer, + fileLinkUrlMapper, builder ).apply { buildBehaviourWithFSMAndStartLongPolling( @@ -113,12 +116,14 @@ suspend fun telegramBotWithBehaviourAndFSMAndStartLongPolling( mediaGroupsDebounceTimeMillis: Long? = 1000L, subcontextInitialAction: CustomBehaviourContextAndTypeReceiver = {}, stateInitialAction: CustomBehaviourContextAndTypeReceiver, Unit, T> = {}, + fileLinkUrlMapper: TelegramAPIUrlsKeeper.(String) -> String = { "${fileBaseUrl}/$it" }, block: CustomBehaviourContextReceiver, Unit> ): Pair { return telegramBot( token, apiUrl, testServer, + fileLinkUrlMapper, builder ).let { it to it.buildBehaviourWithFSMAndStartLongPolling ( diff --git a/tgbotapi.behaviour_builder/api/tgbotapi.behaviour_builder.api b/tgbotapi.behaviour_builder/api/tgbotapi.behaviour_builder.api index 3fb1d8aa1c..96bd4fad6c 100644 --- a/tgbotapi.behaviour_builder/api/tgbotapi.behaviour_builder.api +++ b/tgbotapi.behaviour_builder/api/tgbotapi.behaviour_builder.api @@ -134,10 +134,10 @@ public final class dev/inmo/tgbotapi/extensions/behaviour_builder/DefaultCorouti } public final class dev/inmo/tgbotapi/extensions/behaviour_builder/TelegramBotKt { - public static final fun telegramBotWithBehaviour (Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun telegramBotWithBehaviour$default (Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun telegramBotWithBehaviourAndLongPolling (Ljava/lang/String;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ZIZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun telegramBotWithBehaviourAndLongPolling$default (Ljava/lang/String;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ZIZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static final fun telegramBotWithBehaviour (Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun telegramBotWithBehaviour$default (Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static final fun telegramBotWithBehaviourAndLongPolling (Ljava/lang/String;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ZIZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun telegramBotWithBehaviourAndLongPolling$default (Ljava/lang/String;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ZIZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; } public final class dev/inmo/tgbotapi/extensions/behaviour_builder/VariantsKt { diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/TelegramBot.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/TelegramBot.kt index aa6c72fea4..d4f0afc3d6 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/TelegramBot.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/TelegramBot.kt @@ -1,3 +1,5 @@ +@file:Suppress("unused") + package dev.inmo.tgbotapi.extensions.behaviour_builder import dev.inmo.micro_utils.coroutines.ExceptionHandler @@ -9,6 +11,7 @@ import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.updateHandlerWithMe import dev.inmo.tgbotapi.types.Seconds import dev.inmo.tgbotapi.types.update.abstracts.Update import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter +import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl import kotlinx.coroutines.* import kotlin.coroutines.coroutineContext @@ -35,11 +38,13 @@ suspend fun telegramBotWithBehaviour( defaultExceptionsHandler: ExceptionHandler? = null, testServer: Boolean = false, subcontextInitialAction: CustomBehaviourContextAndTypeReceiver = {}, + fileLinkUrlMapper: TelegramAPIUrlsKeeper.(String) -> String = { "${fileBaseUrl}/$it" }, block: BehaviourContextReceiver ): TelegramBot = telegramBot( token, apiUrl, testServer, + fileLinkUrlMapper, builder ).apply { buildBehaviour( @@ -80,12 +85,14 @@ suspend fun telegramBotWithBehaviourAndLongPolling( autoSkipTimeoutExceptions: Boolean = true, mediaGroupsDebounceTimeMillis: Long? = 1000L, subcontextInitialAction: CustomBehaviourContextAndTypeReceiver = {}, + fileLinkUrlMapper: TelegramAPIUrlsKeeper.(String) -> String = { "${fileBaseUrl}/$it" }, block: BehaviourContextReceiver ): Pair { return telegramBot( token, apiUrl, testServer, + fileLinkUrlMapper, builder ).let { it to it.buildBehaviourWithLongPolling( diff --git a/tgbotapi.core/api/tgbotapi.core.api b/tgbotapi.core/api/tgbotapi.core.api index 493cc8a123..ef4a3c43cf 100644 --- a/tgbotapi.core/api/tgbotapi.core.api +++ b/tgbotapi.core/api/tgbotapi.core.api @@ -377,9 +377,9 @@ public final class dev/inmo/tgbotapi/bot/ktor/KtorRequestsExecutorFactoriesKt { public static final fun createTelegramBotDefaultKtorCallRequestsFactories (Ldev/inmo/kslog/common/KSLog;)Ljava/util/List; public static synthetic fun createTelegramBotDefaultKtorCallRequestsFactories$default (Ldev/inmo/kslog/common/KSLog;ILjava/lang/Object;)Ljava/util/List; public static final fun telegramBot (Ldev/inmo/tgbotapi/utils/TelegramAPIUrlsKeeper;Lkotlin/jvm/functions/Function1;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; - public static final fun telegramBot (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; + public static final fun telegramBot (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; public static synthetic fun telegramBot$default (Ldev/inmo/tgbotapi/utils/TelegramAPIUrlsKeeper;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; - public static synthetic fun telegramBot$default (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; + public static synthetic fun telegramBot$default (Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/inmo/tgbotapi/bot/RequestsExecutor; } public final class dev/inmo/tgbotapi/bot/ktor/KtorRequestsExecutorKt { @@ -30832,10 +30832,12 @@ public final class dev/inmo/tgbotapi/utils/StringFileExtensionKt { } public final class dev/inmo/tgbotapi/utils/TelegramAPIUrlsKeeper { - public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V - public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public fun (Ljava/lang/String;ZLjava/lang/String;)V - public synthetic fun (Ljava/lang/String;ZLjava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public static final field Companion Ldev/inmo/tgbotapi/utils/TelegramAPIUrlsKeeper$Companion; + public static final field DEFAULT_URL Ljava/lang/String; + public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Ljava/lang/String;ZLjava/lang/String;Lkotlin/jvm/functions/Function2;)V + public synthetic fun (Ljava/lang/String;ZLjava/lang/String;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun checkWebAppData (Ljava/lang/String;Ljava/lang/String;)Z public final fun createFileLinkUrl (Ljava/lang/String;)Ljava/lang/String; public final fun getCommonAPIUrl ()Ljava/lang/String; @@ -30844,6 +30846,9 @@ public final class dev/inmo/tgbotapi/utils/TelegramAPIUrlsKeeper { public final fun getWebAppDataSecretKeyHash ()Lkorlibs/crypto/Hash; } +public final class dev/inmo/tgbotapi/utils/TelegramAPIUrlsKeeper$Companion { +} + public final class dev/inmo/tgbotapi/utils/TelegramAPIUrlsKeeperKt { public static final field telegramBotAPIDefaultUrl Ljava/lang/String; } diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/KtorRequestsExecutorFactories.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/KtorRequestsExecutorFactories.kt index d11fe7405d..fe63166cc5 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/KtorRequestsExecutorFactories.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/KtorRequestsExecutorFactories.kt @@ -53,11 +53,19 @@ inline fun telegramBot( /** * Shortcut for [telegramBot] */ -@Suppress("NOTHING_TO_INLINE") -inline fun telegramBot( +fun telegramBot( token: String, apiUrl: String = telegramBotAPIDefaultUrl, testServer: Boolean = false, + fileLinkUrlMapper: TelegramAPIUrlsKeeper.(String) -> String = { "${fileBaseUrl}/$it" }, builder: KtorRequestsExecutorBuilder.() -> Unit = {} -): TelegramBot = telegramBot(TelegramAPIUrlsKeeper(token, testServer, apiUrl), builder) +): TelegramBot = telegramBot( + telegramAPIUrlsKeeper = TelegramAPIUrlsKeeper( + token = token, + testServer = testServer, + hostUrl = apiUrl, + fileLinkUrlMapper = fileLinkUrlMapper + ), + builder = builder +) diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/DownloadFileChannelRequestCallFactory.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/DownloadFileChannelRequestCallFactory.kt index 4a1f3a5d54..548b4c800e 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/DownloadFileChannelRequestCallFactory.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/DownloadFileChannelRequestCallFactory.kt @@ -1,6 +1,5 @@ package dev.inmo.tgbotapi.bot.ktor.base -import dev.inmo.micro_utils.coroutines.* import dev.inmo.tgbotapi.bot.ktor.KtorCallFactory import dev.inmo.tgbotapi.requests.DownloadFileStream import dev.inmo.tgbotapi.requests.abstracts.Request @@ -22,7 +21,17 @@ object DownloadFileChannelRequestCallFactory : KtorCallFactory { request: Request, jsonFormatter: Json ): T? = (request as? DownloadFileStream) ?.let { - val fullUrl = urlsKeeper.createFileLinkUrl(it.filePath) + val bodyChannelAllocator: suspend () -> ByteReadChannel = resolveFile(it.filePath) ?.let { + { + byteReadChannel(it) + } + } ?: let { _ -> + val fullUrl = urlsKeeper.createFileLinkUrl(it.filePath) + return@let { + val response = client.get(fullUrl) + response.bodyAsChannel() + } + } @Suppress("UNCHECKED_CAST") ByteReadChannelAllocator { @@ -30,8 +39,7 @@ object DownloadFileChannelRequestCallFactory : KtorCallFactory { val outChannel = ByteChannel() scope.launch { runCatching { - val response = client.get(fullUrl) - val channel: ByteReadChannel = response.bodyAsChannel() + val channel: ByteReadChannel = bodyChannelAllocator() channel.copyAndClose(outChannel) } scope.cancel() diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/DownloadFileRequestCallFactory.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/DownloadFileRequestCallFactory.kt index 1b77b10a71..4fc2172b8f 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/DownloadFileRequestCallFactory.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/DownloadFileRequestCallFactory.kt @@ -1,5 +1,6 @@ package dev.inmo.tgbotapi.bot.ktor.base +import dev.inmo.micro_utils.common.bytes import dev.inmo.micro_utils.coroutines.safely import dev.inmo.tgbotapi.bot.ktor.KtorCallFactory import dev.inmo.tgbotapi.requests.DownloadFile @@ -19,6 +20,10 @@ object DownloadFileRequestCallFactory : KtorCallFactory { request: Request, jsonFormatter: Json, ): T? = (request as? DownloadFile)?.let { + resolveFile(it.filePath) ?.let { + return@makeCall it.bytes() as T // Always ByteArray + } + val fullUrl = urlsKeeper.createFileLinkUrl(it.filePath) @Suppress("UNCHECKED_CAST") diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FilesWorkaround.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FilesWorkaround.kt new file mode 100644 index 0000000000..6df0a80545 --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FilesWorkaround.kt @@ -0,0 +1,10 @@ +package dev.inmo.tgbotapi.bot.ktor.base + +import dev.inmo.micro_utils.common.MPPFile +import dev.inmo.micro_utils.ktor.common.input +import io.ktor.utils.io.ByteReadChannel + +internal fun byteReadChannel(file: MPPFile): ByteReadChannel { + return ByteReadChannel(file.input()) +} +internal expect fun resolveFile(filename: String): MPPFile? \ No newline at end of file diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/TelegramAPIUrlsKeeper.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/TelegramAPIUrlsKeeper.kt index c0ffcf536c..e186071728 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/TelegramAPIUrlsKeeper.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/TelegramAPIUrlsKeeper.kt @@ -4,8 +4,6 @@ import korlibs.crypto.* import io.ktor.http.decodeURLQueryComponent import io.ktor.utils.io.core.toByteArray -const val telegramBotAPIDefaultUrl = "https://api.telegram.org" - private inline val String.withoutLastSlash: String get() { var correctedUrl = this @@ -21,7 +19,8 @@ private inline val String.withoutLastSlash: String class TelegramAPIUrlsKeeper( token: String, hostUrl: String = telegramBotAPIDefaultUrl, - urlsSuffixes: String = "" + urlsSuffixes: String = "", + private val fileLinkUrlMapper: TelegramAPIUrlsKeeper.(String) -> String = { "${fileBaseUrl}/$it" } ) { val webAppDataSecretKeyHash by lazy { HMAC.hmacSHA256("WebAppData".toByteArray(), token.toByteArray()) @@ -32,10 +31,16 @@ class TelegramAPIUrlsKeeper( val commonAPIUrl: String val fileBaseUrl: String - constructor(token: String, testServer: Boolean, hostUrl: String = telegramBotAPIDefaultUrl) : this( - token, - hostUrl, - "/test".takeIf { testServer } ?: "" + constructor( + token: String, + testServer: Boolean, + hostUrl: String = telegramBotAPIDefaultUrl, + fileLinkUrlMapper: TelegramAPIUrlsKeeper.(String) -> String = { "${fileBaseUrl}/$it" } + ) : this( + token = token, + hostUrl = hostUrl, + urlsSuffixes = "/test".takeIf { testServer } ?: "", + fileLinkUrlMapper = fileLinkUrlMapper ) init { @@ -44,7 +49,7 @@ class TelegramAPIUrlsKeeper( fileBaseUrl = "$correctedHost/file/bot$token$urlsSuffixes" } - fun createFileLinkUrl(filePath: String) = "${fileBaseUrl}/$filePath" + fun createFileLinkUrl(filePath: String) = fileLinkUrlMapper(filePath) /** * @param rawData Data from [dev.inmo.tgbotapi.webapps.WebApp.initData] @@ -60,4 +65,10 @@ class TelegramAPIUrlsKeeper( return HMAC.hmacSHA256(webAppDataSecretKeyHash.bytes, preparedData.toByteArray()).hexLower == hash.lowercase() } + + companion object { + const val DEFAULT_URL = "https://api.telegram.org" + } } + +const val telegramBotAPIDefaultUrl = TelegramAPIUrlsKeeper.DEFAULT_URL diff --git a/tgbotapi.core/src/jsMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.js.kt b/tgbotapi.core/src/jsMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.js.kt new file mode 100644 index 0000000000..f3ea23e4cf --- /dev/null +++ b/tgbotapi.core/src/jsMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.js.kt @@ -0,0 +1,5 @@ +package dev.inmo.tgbotapi.bot.ktor.base + +import dev.inmo.micro_utils.common.MPPFile + +internal actual fun resolveFile(filename: String): MPPFile? = null // on JS in common case there is no opportunity to take file based on its name \ No newline at end of file diff --git a/tgbotapi.core/src/jvmMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.jvm.kt b/tgbotapi.core/src/jvmMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.jvm.kt new file mode 100644 index 0000000000..de6d101859 --- /dev/null +++ b/tgbotapi.core/src/jvmMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.jvm.kt @@ -0,0 +1,7 @@ +package dev.inmo.tgbotapi.bot.ktor.base + +import dev.inmo.micro_utils.common.MPPFile + +internal actual fun resolveFile(filename: String): MPPFile? = runCatching { + MPPFile(filename).takeIf { it.exists() && it.isFile } +}.getOrElse { null } diff --git a/tgbotapi.core/src/mingwX64Main/kotlin/dev/inmo/tgbotapi/bot/ktor/base/ActualPlatformClientCopy.kt b/tgbotapi.core/src/mingwX64Main/kotlin/bot/ktor/base/ActualPlatformClientCopy.kt similarity index 100% rename from tgbotapi.core/src/mingwX64Main/kotlin/dev/inmo/tgbotapi/bot/ktor/base/ActualPlatformClientCopy.kt rename to tgbotapi.core/src/mingwX64Main/kotlin/bot/ktor/base/ActualPlatformClientCopy.kt diff --git a/tgbotapi.core/src/nativeMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.native.kt b/tgbotapi.core/src/nativeMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.native.kt new file mode 100644 index 0000000000..e4a1de5fd7 --- /dev/null +++ b/tgbotapi.core/src/nativeMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.native.kt @@ -0,0 +1,11 @@ +package dev.inmo.tgbotapi.bot.ktor.base + +import okio.FileSystem +import okio.Path +import okio.Path.Companion.toPath + +internal actual fun resolveFile(filename: String): dev.inmo.micro_utils.common.MPPFile? = runCatching { + with(Path) { filename.toPath() }.takeIf { + FileSystem.SYSTEM.exists(it) && FileSystem.SYSTEM.metadata(it).isRegularFile + } +}.getOrElse { null } \ No newline at end of file