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