From 5e5dc6b36bbc43632410c911a70ee91f2a9f2eb6 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 25 Jul 2025 21:00:44 +0600 Subject: [PATCH 1/6] start 27.1.0 --- CHANGELOG.md | 2 ++ gradle.properties | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8057dbdc4..624f83195c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # TelegramBotAPI changelog +## 27.1.0 + ## 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/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 From cec5a0af121fc69ccc975a80bdc41bc5ff0ade07 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 25 Jul 2025 21:35:38 +0600 Subject: [PATCH 2/6] improve support of local bot api servers --- CHANGELOG.md | 5 +++++ .../DownloadFileChannelRequestCallFactory.kt | 16 ++++++++++++---- .../ktor/base/DownloadFileRequestCallFactory.kt | 5 +++++ .../tgbotapi/bot/ktor/base/FilesWorkaround.kt | 10 ++++++++++ .../tgbotapi/bot/ktor/base/FileResolver.js.kt | 5 +++++ .../tgbotapi/bot/ktor/base/FileResolver.jvm.kt | 7 +++++++ .../bot/ktor/base/FileResolver.linuxArm64.kt | 11 +++++++++++ .../tgbotapi/bot/ktor/base/FileResolver.linux.kt | 10 ++++++++++ .../bot/ktor/base/FileResolver.linuxX64.kt | 11 +++++++++++ .../tgbotapi/bot/ktor/base/FileResolver.mingw.kt | 11 +++++++++++ .../bot/ktor/base/ActualPlatformClientCopy.kt | 0 .../bot/ktor/base/FileResolver.mingwX64.kt | 12 ++++++++++++ .../bot/ktor/base/FileResolver.native.kt | 11 +++++++++++ 13 files changed, 110 insertions(+), 4 deletions(-) create mode 100644 tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FilesWorkaround.kt create mode 100644 tgbotapi.core/src/jsMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.js.kt create mode 100644 tgbotapi.core/src/jvmMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.jvm.kt create mode 100644 tgbotapi.core/src/linuxArm64Main/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.linuxArm64.kt create mode 100644 tgbotapi.core/src/linuxMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.linux.kt create mode 100644 tgbotapi.core/src/linuxX64Main/kotlin/bot/ktor/base/FileResolver.linuxX64.kt create mode 100644 tgbotapi.core/src/mingwMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.mingw.kt rename tgbotapi.core/src/mingwX64Main/kotlin/{dev/inmo/tgbotapi => }/bot/ktor/base/ActualPlatformClientCopy.kt (100%) create mode 100644 tgbotapi.core/src/mingwX64Main/kotlin/bot/ktor/base/FileResolver.mingwX64.kt create mode 100644 tgbotapi.core/src/nativeMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.native.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 624f83195c..0b4fcd9fc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## 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/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/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/linuxArm64Main/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.linuxArm64.kt b/tgbotapi.core/src/linuxArm64Main/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.linuxArm64.kt new file mode 100644 index 0000000000..cc3da73f5c --- /dev/null +++ b/tgbotapi.core/src/linuxArm64Main/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.linuxArm64.kt @@ -0,0 +1,11 @@ +package dev.inmo.tgbotapi.bot.ktor.base + +import dev.inmo.micro_utils.common.MPPFile +import okio.FileSystem +import okio.Path + +internal actual fun resolveFile(filename: String): MPPFile? = runCatching { + with(Path) { filename.toPath() }.takeIf { + FileSystem.SYSTEM.exists(it) && FileSystem.SYSTEM.metadata(it).isRegularFile + } +}.getOrElse { null } \ No newline at end of file diff --git a/tgbotapi.core/src/linuxMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.linux.kt b/tgbotapi.core/src/linuxMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.linux.kt new file mode 100644 index 0000000000..ddc3bf8dd5 --- /dev/null +++ b/tgbotapi.core/src/linuxMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.linux.kt @@ -0,0 +1,10 @@ +package dev.inmo.tgbotapi.bot.ktor.base + +import okio.FileSystem +import okio.Path + +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 diff --git a/tgbotapi.core/src/linuxX64Main/kotlin/bot/ktor/base/FileResolver.linuxX64.kt b/tgbotapi.core/src/linuxX64Main/kotlin/bot/ktor/base/FileResolver.linuxX64.kt new file mode 100644 index 0000000000..cc3da73f5c --- /dev/null +++ b/tgbotapi.core/src/linuxX64Main/kotlin/bot/ktor/base/FileResolver.linuxX64.kt @@ -0,0 +1,11 @@ +package dev.inmo.tgbotapi.bot.ktor.base + +import dev.inmo.micro_utils.common.MPPFile +import okio.FileSystem +import okio.Path + +internal actual fun resolveFile(filename: String): MPPFile? = runCatching { + with(Path) { filename.toPath() }.takeIf { + FileSystem.SYSTEM.exists(it) && FileSystem.SYSTEM.metadata(it).isRegularFile + } +}.getOrElse { null } \ No newline at end of file diff --git a/tgbotapi.core/src/mingwMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.mingw.kt b/tgbotapi.core/src/mingwMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.mingw.kt new file mode 100644 index 0000000000..e4a1de5fd7 --- /dev/null +++ b/tgbotapi.core/src/mingwMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.mingw.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 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/mingwX64Main/kotlin/bot/ktor/base/FileResolver.mingwX64.kt b/tgbotapi.core/src/mingwX64Main/kotlin/bot/ktor/base/FileResolver.mingwX64.kt new file mode 100644 index 0000000000..1d08540d3a --- /dev/null +++ b/tgbotapi.core/src/mingwX64Main/kotlin/bot/ktor/base/FileResolver.mingwX64.kt @@ -0,0 +1,12 @@ +package dev.inmo.tgbotapi.bot.ktor.base + +import dev.inmo.micro_utils.common.MPPFile +import okio.FileSystem +import okio.Path +import okio.Path.Companion.toPath + +internal actual fun resolveFile(filename: String): MPPFile? = runCatching { + with(Path) { filename.toPath() }.takeIf { + FileSystem.SYSTEM.exists(it) && FileSystem.SYSTEM.metadata(it).isRegularFile + } +}.getOrElse { null } \ No newline at end of file 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 From 2f4de374894b8a698631609bceec91dbbce217f3 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 25 Jul 2025 21:53:08 +0600 Subject: [PATCH 3/6] fix build --- .../bot/ktor/base/FileResolver.linuxArm64.kt | 11 ----------- .../tgbotapi/bot/ktor/base/FileResolver.linux.kt | 10 ---------- .../kotlin/bot/ktor/base/FileResolver.linuxX64.kt | 11 ----------- .../tgbotapi/bot/ktor/base/FileResolver.mingw.kt | 11 ----------- .../kotlin/bot/ktor/base/FileResolver.mingwX64.kt | 12 ------------ 5 files changed, 55 deletions(-) delete mode 100644 tgbotapi.core/src/linuxArm64Main/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.linuxArm64.kt delete mode 100644 tgbotapi.core/src/linuxMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.linux.kt delete mode 100644 tgbotapi.core/src/linuxX64Main/kotlin/bot/ktor/base/FileResolver.linuxX64.kt delete mode 100644 tgbotapi.core/src/mingwMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.mingw.kt delete mode 100644 tgbotapi.core/src/mingwX64Main/kotlin/bot/ktor/base/FileResolver.mingwX64.kt diff --git a/tgbotapi.core/src/linuxArm64Main/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.linuxArm64.kt b/tgbotapi.core/src/linuxArm64Main/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.linuxArm64.kt deleted file mode 100644 index cc3da73f5c..0000000000 --- a/tgbotapi.core/src/linuxArm64Main/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.linuxArm64.kt +++ /dev/null @@ -1,11 +0,0 @@ -package dev.inmo.tgbotapi.bot.ktor.base - -import dev.inmo.micro_utils.common.MPPFile -import okio.FileSystem -import okio.Path - -internal actual fun resolveFile(filename: String): MPPFile? = runCatching { - with(Path) { filename.toPath() }.takeIf { - FileSystem.SYSTEM.exists(it) && FileSystem.SYSTEM.metadata(it).isRegularFile - } -}.getOrElse { null } \ No newline at end of file diff --git a/tgbotapi.core/src/linuxMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.linux.kt b/tgbotapi.core/src/linuxMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.linux.kt deleted file mode 100644 index ddc3bf8dd5..0000000000 --- a/tgbotapi.core/src/linuxMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.linux.kt +++ /dev/null @@ -1,10 +0,0 @@ -package dev.inmo.tgbotapi.bot.ktor.base - -import okio.FileSystem -import okio.Path - -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 diff --git a/tgbotapi.core/src/linuxX64Main/kotlin/bot/ktor/base/FileResolver.linuxX64.kt b/tgbotapi.core/src/linuxX64Main/kotlin/bot/ktor/base/FileResolver.linuxX64.kt deleted file mode 100644 index cc3da73f5c..0000000000 --- a/tgbotapi.core/src/linuxX64Main/kotlin/bot/ktor/base/FileResolver.linuxX64.kt +++ /dev/null @@ -1,11 +0,0 @@ -package dev.inmo.tgbotapi.bot.ktor.base - -import dev.inmo.micro_utils.common.MPPFile -import okio.FileSystem -import okio.Path - -internal actual fun resolveFile(filename: String): MPPFile? = runCatching { - with(Path) { filename.toPath() }.takeIf { - FileSystem.SYSTEM.exists(it) && FileSystem.SYSTEM.metadata(it).isRegularFile - } -}.getOrElse { null } \ No newline at end of file diff --git a/tgbotapi.core/src/mingwMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.mingw.kt b/tgbotapi.core/src/mingwMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.mingw.kt deleted file mode 100644 index e4a1de5fd7..0000000000 --- a/tgbotapi.core/src/mingwMain/kotlin/dev/inmo/tgbotapi/bot/ktor/base/FileResolver.mingw.kt +++ /dev/null @@ -1,11 +0,0 @@ -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 diff --git a/tgbotapi.core/src/mingwX64Main/kotlin/bot/ktor/base/FileResolver.mingwX64.kt b/tgbotapi.core/src/mingwX64Main/kotlin/bot/ktor/base/FileResolver.mingwX64.kt deleted file mode 100644 index 1d08540d3a..0000000000 --- a/tgbotapi.core/src/mingwX64Main/kotlin/bot/ktor/base/FileResolver.mingwX64.kt +++ /dev/null @@ -1,12 +0,0 @@ -package dev.inmo.tgbotapi.bot.ktor.base - -import dev.inmo.micro_utils.common.MPPFile -import okio.FileSystem -import okio.Path -import okio.Path.Companion.toPath - -internal actual fun resolveFile(filename: String): MPPFile? = runCatching { - with(Path) { filename.toPath() }.takeIf { - FileSystem.SYSTEM.exists(it) && FileSystem.SYSTEM.metadata(it).isRegularFile - } -}.getOrElse { null } \ No newline at end of file From 1bc9ee4d5a23866ba1fb89d8316ca3d9252dcc8e Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sun, 27 Jul 2025 15:06:47 +0600 Subject: [PATCH 4/6] add TelegramAPIUrlsKeeper#fileLinkUrlMapper and fill readme Bot API Server Notice --- README.md | 17 +++++++++++++++++ tgbotapi.core/api/tgbotapi.core.api | 4 ++-- .../tgbotapi/utils/TelegramAPIUrlsKeeper.kt | 5 +++-- 3 files changed, 22 insertions(+), 4 deletions(-) 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/tgbotapi.core/api/tgbotapi.core.api b/tgbotapi.core/api/tgbotapi.core.api index 493cc8a123..5b4df7f184 100644 --- a/tgbotapi.core/api/tgbotapi.core.api +++ b/tgbotapi.core/api/tgbotapi.core.api @@ -30832,8 +30832,8 @@ 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;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;)V public synthetic fun (Ljava/lang/String;ZLjava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun checkWebAppData (Ljava/lang/String;Ljava/lang/String;)Z 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..a74d94a870 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 @@ -21,7 +21,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()) @@ -44,7 +45,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] From 3ce56745f425a7ae47da979d4aef1fa2e41dd4c7 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Mon, 28 Jul 2025 20:04:59 +0600 Subject: [PATCH 5/6] add fileLinkUrlMapper to all callers of TelegramAPIUrlsKeeper constructors --- tgbotapi.api/api/tgbotapi.api.api | 20 ++++++------- .../tgbotapi/extensions/api/BotBuilder.kt | 12 ++++++-- .../tgbotapi/extensions/api/BotExtensions.kt | 28 ++++++++++--------- .../api/tgbotapi.behaviour_builder.fsm.api | 8 +++--- .../behaviour_builder/TelegramBotWithFSM.kt | 5 ++++ .../api/tgbotapi.behaviour_builder.api | 8 +++--- .../behaviour_builder/TelegramBot.kt | 7 +++++ tgbotapi.core/api/tgbotapi.core.api | 13 ++++++--- .../bot/ktor/KtorRequestsExecutorFactories.kt | 14 ++++++++-- .../tgbotapi/utils/TelegramAPIUrlsKeeper.kt | 22 +++++++++++---- 10 files changed, 90 insertions(+), 47 deletions(-) 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 5b4df7f184..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 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;)V - public synthetic fun (Ljava/lang/String;ZLjava/lang/String;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/utils/TelegramAPIUrlsKeeper.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/utils/TelegramAPIUrlsKeeper.kt index a74d94a870..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 @@ -33,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 { @@ -61,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 From 2e1c0d41ec50b6f5f23ced593edd90a6ea2209b9 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Mon, 28 Jul 2025 20:09:58 +0600 Subject: [PATCH 6/6] update service dependencies --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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]