1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2024-11-26 03:58:44 +00:00

Merge pull request #440 from InsanusMokrassar/0.35.5

0.35.5
This commit is contained in:
InsanusMokrassar 2021-08-13 20:51:02 +06:00 committed by GitHub
commit 7b1344e9c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 442 additions and 38 deletions

View File

@ -1,5 +1,25 @@
# TelegramBotAPI changelog # TelegramBotAPI changelog
## 0.35.5
**MIME TYPES FOR REQUESTS HAVE BEEN DEPRECATED DUE TO REDUNDANCY OF MIME TYPES IN FILES SENDING**
* `Core`:
* Several new extensions `ByteReadChannel#asStorageFile` and `ByteReadChannelAllocator#asStorageFile`
* Several new extensions `ByteArray#asMultipartFile`, `ByteReadChannel#asMultipartFile` and
`ByteReadChannelAllocator#asMultipartFile`
* New extension `StorageFile#asMultipartFile`
* `API`:
* New extensions `TelegramBot#downloadFile` for writing of incoming bytes to the file
* New extensions `TelegramBot#downloadFileStream` and `TelegramBot#downloadFileStreamAllocator` for getting of input
streams instead of whole bytes arrays
* Old extensions `TelegramBot#downloadFile` has been replaced to the new package. Migration: replace in your project
`import dev.inmo.tgbotapi.extensions.api.downloadFile` with `import dev.inmo.tgbotapi.extensions.api.files.downloadFile`
* `PathedFile#filename` extension has been deprecated, and new property `PathedFile#fileName` has been included
directly in `PathedFile`
* `Utils`:
* Add several functions `convertToStorageFile` and extensions `TelegramBot#convertToStorageFile`
## 0.35.4 Hotfix ## 0.35.4 Hotfix
* `Common`: * `Common`:

View File

@ -17,6 +17,6 @@ micro_utils_version=0.5.19
javax_activation_version=1.1.1 javax_activation_version=1.1.1
library_group=dev.inmo library_group=dev.inmo
library_version=0.35.4 library_version=0.35.5
github_release_plugin_version=2.2.12 github_release_plugin_version=2.2.12

View File

@ -42,6 +42,14 @@ inline fun telegramBot(
crossinline builder: KtorRequestsExecutorBuilder.() -> Unit = {} crossinline builder: KtorRequestsExecutorBuilder.() -> Unit = {}
): TelegramBot = telegramBot(TelegramAPIUrlsKeeper(token, apiUrl), builder) ): TelegramBot = telegramBot(TelegramAPIUrlsKeeper(token, apiUrl), builder)
@RiskFeature
fun createTelegramBotDefaultKtorCallRequestsFactories() = listOf(
SimpleRequestCallFactory(),
MultipartRequestCallFactory(),
DownloadFileRequestCallFactory,
DownloadFileChannelRequestCallFactory
)
class KtorRequestsExecutor( class KtorRequestsExecutor(
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper, telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper,
client: HttpClient = HttpClient(), client: HttpClient = HttpClient(),
@ -52,7 +60,7 @@ class KtorRequestsExecutor(
) : BaseRequestsExecutor(telegramAPIUrlsKeeper) { ) : BaseRequestsExecutor(telegramAPIUrlsKeeper) {
private val callsFactories: List<KtorCallFactory> = callsFactories.run { private val callsFactories: List<KtorCallFactory> = callsFactories.run {
if (!excludeDefaultFactories) { if (!excludeDefaultFactories) {
this + listOf(SimpleRequestCallFactory(), MultipartRequestCallFactory(), DownloadFileRequestCallFactory) this + createTelegramBotDefaultKtorCallRequestsFactories()
} else { } else {
this this
} }

View File

@ -0,0 +1,39 @@
package dev.inmo.tgbotapi.bot.Ktor.base
import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions
import dev.inmo.tgbotapi.bot.Ktor.KtorCallFactory
import dev.inmo.tgbotapi.requests.DownloadFileStream
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.utils.ByteReadChannelAllocator
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import io.ktor.client.HttpClient
import io.ktor.client.call.receive
import io.ktor.client.request.get
import io.ktor.client.statement.HttpStatement
import io.ktor.utils.io.*
import kotlinx.coroutines.*
import kotlinx.serialization.json.Json
import kotlin.coroutines.coroutineContext
object DownloadFileChannelRequestCallFactory : KtorCallFactory {
override suspend fun <T : Any> makeCall(
client: HttpClient,
urlsKeeper: TelegramAPIUrlsKeeper,
request: Request<T>,
jsonFormatter: Json
): T? = (request as? DownloadFileStream) ?.let {
val fullUrl = urlsKeeper.createFileLinkUrl(it.filePath)
ByteReadChannelAllocator {
val scope = CoroutineScope(coroutineContext)
val outChannel = ByteChannel()
scope.launchSafelyWithoutExceptions {
client.get<HttpStatement>(fullUrl).execute { httpResponse ->
val channel: ByteReadChannel = httpResponse.receive()
channel.copyAndClose(outChannel)
}
}
outChannel
} as T
}
}

View File

@ -16,9 +16,9 @@ object DownloadFileRequestCallFactory : KtorCallFactory {
request: Request<T>, request: Request<T>,
jsonFormatter: Json jsonFormatter: Json
): T? = (request as? DownloadFile) ?.let { ): T? = (request as? DownloadFile) ?.let {
val fullUrl = "${urlsKeeper.fileBaseUrl}/${it.filePath}" val fullUrl = urlsKeeper.createFileLinkUrl(it.filePath)
return safely { safely {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
client.get<ByteArray>(fullUrl) as T // always ByteArray client.get<ByteArray>(fullUrl) as T // always ByteArray
} }

View File

@ -24,7 +24,6 @@ class MultipartRequestCallFactory : AbstractRequestCallFactory() {
is MultipartFile -> appendInput( is MultipartFile -> appendInput(
key, key,
Headers.build { Headers.build {
append(HttpHeaders.ContentType, value.mimeType)
append(HttpHeaders.ContentDisposition, "filename=${value.fileId}") append(HttpHeaders.ContentDisposition, "filename=${value.fileId}")
}, },
block = value.file::input block = value.file::input

View File

@ -0,0 +1,15 @@
package dev.inmo.tgbotapi.requests
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.utils.ByteReadChannelAllocator
import dev.inmo.tgbotapi.utils.ByteReadChannelAllocatorDeserializationStrategy
import kotlinx.serialization.DeserializationStrategy
class DownloadFileStream(
val filePath: String
) : Request<ByteReadChannelAllocator> {
override fun method(): String = filePath
override val resultDeserializer: DeserializationStrategy<ByteReadChannelAllocator>
get() = ByteReadChannelAllocatorDeserializationStrategy
}

View File

@ -1,7 +1,7 @@
package dev.inmo.tgbotapi.requests.abstracts package dev.inmo.tgbotapi.requests.abstracts
import dev.inmo.tgbotapi.utils.RiskFeature import dev.inmo.tgbotapi.utils.*
import dev.inmo.tgbotapi.utils.StorageFile import io.ktor.utils.io.ByteReadChannel
import kotlinx.serialization.KSerializer import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.* import kotlinx.serialization.descriptors.*
@ -42,12 +42,36 @@ object InputFileSerializer : KSerializer<InputFile> {
// TODO:: add checks for files size // TODO:: add checks for files size
/** /**
* Contains info about file for sending * Contains info about file for sending
*
* @see asMultipartFile
*/ */
@Serializable(InputFileSerializer::class) @Serializable(InputFileSerializer::class)
data class MultipartFile ( data class MultipartFile (
val file: StorageFile, val file: StorageFile,
val mimeType: String = file.storageFileInfo.contentType,
val filename: String = file.storageFileInfo.fileName val filename: String = file.storageFileInfo.fileName
) : InputFile() { ) : InputFile() {
override val fileId: String = file.storageFileInfo.generateCustomName() override val fileId: String = file.storageFileInfo.generateCustomName()
@Deprecated("This constructor is redundant. Use constructor without mime type")
constructor(file: StorageFile, mimeType: String, filename: String): this(file, filename)
} }
@Suppress("NOTHING_TO_INLINE", "unused")
inline fun StorageFile.asMultipartFile() = MultipartFile(this)
@Deprecated("This method is redundant. Use asMultipartFile without mime type")
@Suppress("NOTHING_TO_INLINE", "unused")
inline fun ByteArray.asMultipartFile(
fileName: String,
mimeType: MimeType
) = MultipartFile(asStorageFile(fileName))
@Suppress("NOTHING_TO_INLINE", "unused")
suspend inline fun ByteReadChannel.asMultipartFile(
fileName: String
) = MultipartFile(asStorageFile(fileName))
@Suppress("NOTHING_TO_INLINE", "unused")
suspend inline fun ByteReadChannelAllocator.asMultipartFile(
fileName: String
) = this.invoke().asMultipartFile(fileName)

View File

@ -5,8 +5,7 @@ import dev.inmo.tgbotapi.types.FileUniqueId
import dev.inmo.tgbotapi.types.fileUniqueIdField import dev.inmo.tgbotapi.types.fileUniqueIdField
import dev.inmo.tgbotapi.types.files.abstracts.* import dev.inmo.tgbotapi.types.files.abstracts.*
import dev.inmo.tgbotapi.utils.* import dev.inmo.tgbotapi.utils.*
import kotlinx.serialization.SerialName import kotlinx.serialization.*
import kotlinx.serialization.Serializable
@Serializable @Serializable
data class PathedFile( data class PathedFile(
@ -18,8 +17,14 @@ data class PathedFile(
val filePath: String, val filePath: String,
@SerialName(fileSizeField) @SerialName(fileSizeField)
override val fileSize: Long? = null override val fileSize: Long? = null
): TelegramMediaFile ): TelegramMediaFile {
@Transient
val fileName: FileName by lazy(LazyThreadSafetyMode.PUBLICATION) {
filePath.filenameFromUrl
}
}
@Deprecated("Use fileName property instead", ReplaceWith("fileName"))
val PathedFile.filename: FileName val PathedFile.filename: FileName
get() = filePath.filenameFromUrl get() = filePath.filenameFromUrl
fun TelegramAPIUrlsKeeper.resolveFileURL(file: PathedFile): String = "$fileBaseUrl/${file.filePath}" fun TelegramAPIUrlsKeeper.resolveFileURL(file: PathedFile): String = "$fileBaseUrl/${file.filePath}"

View File

@ -8,4 +8,11 @@ object BuiltinMimeTypes {
object Video { object Video {
val MP4 = buildMimeType("video/mp4") val MP4 = buildMimeType("video/mp4")
} }
object Text {
val Html = buildMimeType("text/html")
}
object Application {
val Zip = buildMimeType("application/zip")
val Pdf = buildMimeType("application/pdf")
}
} }

View File

@ -0,0 +1,22 @@
package dev.inmo.tgbotapi.utils
import dev.inmo.micro_utils.common.ByteArrayAllocatorSerializer
import io.ktor.utils.io.ByteReadChannel
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
fun interface ByteReadChannelAllocator {
suspend operator fun invoke(): ByteReadChannel
}
object ByteReadChannelAllocatorDeserializationStrategy : DeserializationStrategy<ByteReadChannelAllocator> {
override val descriptor: SerialDescriptor = ByteArrayAllocatorSerializer.descriptor
override fun deserialize(decoder: Decoder): ByteReadChannelAllocator {
val byteArrayAllocator = ByteArrayAllocatorSerializer.deserialize(decoder)
return ByteReadChannelAllocator { ByteReadChannel(byteArrayAllocator()) }
}
}

View File

@ -0,0 +1,6 @@
package dev.inmo.tgbotapi.utils
import io.ktor.utils.io.ByteReadChannel
import io.ktor.utils.io.core.Input
expect suspend fun ByteReadChannel.asInput(): Input

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.utils package dev.inmo.tgbotapi.utils
import com.benasher44.uuid.uuid4 import com.benasher44.uuid.uuid4
import io.ktor.utils.io.*
import io.ktor.utils.io.core.ByteReadPacket import io.ktor.utils.io.core.ByteReadPacket
import io.ktor.utils.io.core.Input import io.ktor.utils.io.core.Input
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -13,9 +14,14 @@ import kotlinx.serialization.Serializable
*/ */
@Serializable @Serializable
data class StorageFileInfo( data class StorageFileInfo(
val contentType: String,
val fileName: String val fileName: String
) { ) {
@Deprecated("This constructor is redundant. Use constructor without mime type")
constructor(
contentType: String,
fileName: String
): this(fileName)
/** /**
* This methods is required for random generation of name for keeping warranties about unique file name * This methods is required for random generation of name for keeping warranties about unique file name
*/ */
@ -39,19 +45,55 @@ data class StorageFile(
get() = inputSource() get() = inputSource()
} }
@Deprecated("This constructor is redundant. Use constructor without mime type")
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
inline fun StorageFile( inline fun StorageFile(
fileName: String, fileName: String,
bytes: ByteArray, bytes: ByteArray,
mimeType: MimeType mimeType: MimeType
) = StorageFile( ) = StorageFile(
StorageFileInfo(mimeType.raw, fileName) StorageFileInfo(fileName)
) { ) {
ByteReadPacket(bytes) ByteReadPacket(bytes)
} }
/** @Suppress("NOTHING_TO_INLINE")
* inline fun StorageFile(
*/ fileName: String,
bytes: ByteArray
) = StorageFile(
StorageFileInfo(fileName)
) {
ByteReadPacket(bytes)
}
@Suppress("NOTHING_TO_INLINE")
suspend inline fun StorageFile(
fileName: String,
byteReadChannel: ByteReadChannel
) = StorageFile(
StorageFileInfo(fileName),
byteReadChannel.asInput().let { { it } }
)
@Suppress("NOTHING_TO_INLINE", "unused") @Suppress("NOTHING_TO_INLINE", "unused")
inline fun ByteArray.asStorageFile(fileName: String, mimeType: MimeType) = StorageFile(fileName, this, mimeType) inline fun ByteArray.asStorageFile(
fileName: String
) = StorageFile(fileName, this)
@Deprecated("This constructor is redundant. Use constructor without mime type")
@Suppress("NOTHING_TO_INLINE", "unused")
inline fun ByteArray.asStorageFile(
fileName: String,
mimeType: MimeType
) = asStorageFile(fileName)
@Suppress("NOTHING_TO_INLINE", "unused")
suspend inline fun ByteReadChannel.asStorageFile(
fileName: String
) = StorageFile(fileName, this)
@Suppress("NOTHING_TO_INLINE", "unused")
suspend inline fun ByteReadChannelAllocator.asStorageFile(
fileName: String
) = this.invoke().asStorageFile(fileName)

View File

@ -26,4 +26,6 @@ class TelegramAPIUrlsKeeper(
commonAPIUrl = "$correctedHost/bot$token" commonAPIUrl = "$correctedHost/bot$token"
fileBaseUrl = "$correctedHost/file/bot$token" fileBaseUrl = "$correctedHost/file/bot$token"
} }
fun createFileLinkUrl(filePath: String) = "${fileBaseUrl}/$filePath"
} }

View File

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

View File

@ -7,10 +7,7 @@ import java.nio.file.Files
fun StorageFile( fun StorageFile(
file: File file: File
) = StorageFile( ) = StorageFile(
StorageFileInfo( StorageFileInfo(file.name)
Files.probeContentType(file.toPath()),
file.name
)
) { ) {
file.inputStream().asInput() file.inputStream().asInput()
} }

View File

@ -0,0 +1,10 @@
package dev.inmo.tgbotapi.utils
import io.ktor.utils.io.ByteReadChannel
import io.ktor.utils.io.core.Input
import io.ktor.utils.io.jvm.javaio.toInputStream
import io.ktor.utils.io.streams.asInput
import kotlinx.coroutines.job
import kotlin.coroutines.coroutineContext
actual suspend fun ByteReadChannel.asInput(): Input = toInputStream(coroutineContext.job).asInput()

View File

@ -1,39 +1,33 @@
package dev.inmo.tgbotapi.extensions.api package dev.inmo.tgbotapi.extensions.api
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.api.get.getFileAdditionalInfo import dev.inmo.tgbotapi.extensions.api.files.downloadFile
import dev.inmo.tgbotapi.requests.DownloadFile
import dev.inmo.tgbotapi.requests.abstracts.FileId import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.types.files.PathedFile import dev.inmo.tgbotapi.types.files.PathedFile
import dev.inmo.tgbotapi.types.files.abstracts.TelegramMediaFile import dev.inmo.tgbotapi.types.files.abstracts.TelegramMediaFile
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
@Deprecated("Replaced", ReplaceWith("downloadFile", "dev.inmo.tgbotapi.extensions.api.files.downloadFile"))
suspend fun TelegramBot.downloadFile( suspend fun TelegramBot.downloadFile(
filePath: String filePath: String
): ByteArray = execute( ): ByteArray = downloadFile(filePath)
DownloadFile(filePath)
)
@Deprecated("Replaced", ReplaceWith("downloadFile", "dev.inmo.tgbotapi.extensions.api.files.downloadFile"))
suspend fun TelegramBot.downloadFile( suspend fun TelegramBot.downloadFile(
pathedFile: PathedFile pathedFile: PathedFile
): ByteArray = execute( ): ByteArray = downloadFile(pathedFile)
DownloadFile(pathedFile.filePath)
)
@Deprecated("Replaced", ReplaceWith("downloadFile", "dev.inmo.tgbotapi.extensions.api.files.downloadFile"))
suspend fun TelegramBot.downloadFile( suspend fun TelegramBot.downloadFile(
fileId: FileId fileId: FileId
): ByteArray = downloadFile( ): ByteArray = downloadFile(fileId)
getFileAdditionalInfo(fileId)
)
@Deprecated("Replaced", ReplaceWith("downloadFile", "dev.inmo.tgbotapi.extensions.api.files.downloadFile"))
suspend fun TelegramBot.downloadFile( suspend fun TelegramBot.downloadFile(
file: TelegramMediaFile file: TelegramMediaFile
): ByteArray = downloadFile( ): ByteArray = downloadFile(file)
getFileAdditionalInfo(file)
)
@Deprecated("Replaced", ReplaceWith("downloadFile", "dev.inmo.tgbotapi.extensions.api.files.downloadFile"))
suspend fun TelegramBot.downloadFile( suspend fun TelegramBot.downloadFile(
file: MediaContent file: MediaContent
): ByteArray = downloadFile( ): ByteArray = downloadFile(file)
getFileAdditionalInfo(file.media)
)

View File

@ -0,0 +1,39 @@
package dev.inmo.tgbotapi.extensions.api.files
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.api.get.getFileAdditionalInfo
import dev.inmo.tgbotapi.requests.DownloadFile
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.types.files.PathedFile
import dev.inmo.tgbotapi.types.files.abstracts.TelegramMediaFile
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
suspend fun TelegramBot.downloadFile(
filePath: String
): ByteArray = execute(
DownloadFile(filePath)
)
suspend fun TelegramBot.downloadFile(
pathedFile: PathedFile
): ByteArray = downloadFile(
pathedFile.filePath
)
suspend fun TelegramBot.downloadFile(
fileId: FileId
): ByteArray = downloadFile(
getFileAdditionalInfo(fileId)
)
suspend fun TelegramBot.downloadFile(
file: TelegramMediaFile
): ByteArray = downloadFile(
getFileAdditionalInfo(file)
)
suspend fun TelegramBot.downloadFile(
file: MediaContent
): ByteArray = downloadFile(
getFileAdditionalInfo(file.media)
)

View File

@ -0,0 +1,29 @@
package dev.inmo.tgbotapi.extensions.api.files
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.api.get.getFileAdditionalInfo
import dev.inmo.tgbotapi.requests.DownloadFileStream
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.types.files.PathedFile
import dev.inmo.tgbotapi.types.files.abstracts.TelegramMediaFile
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
suspend fun TelegramBot.downloadFileStream(
filePath: String
) = downloadFileStreamAllocator(filePath).invoke()
suspend fun TelegramBot.downloadFileStream(
pathedFile: PathedFile
) = downloadFileStream(pathedFile.filePath)
suspend fun TelegramBot.downloadFileStream(
fileId: FileId
) = downloadFileStream(getFileAdditionalInfo(fileId))
suspend fun TelegramBot.downloadFileStream(
file: TelegramMediaFile
) = downloadFileStream(getFileAdditionalInfo(file))
suspend fun TelegramBot.downloadFileStream(
file: MediaContent
) = downloadFileStream(getFileAdditionalInfo(file.media))

View File

@ -0,0 +1,29 @@
package dev.inmo.tgbotapi.extensions.api.files
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.api.get.getFileAdditionalInfo
import dev.inmo.tgbotapi.requests.DownloadFileStream
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.types.files.PathedFile
import dev.inmo.tgbotapi.types.files.abstracts.TelegramMediaFile
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
suspend fun TelegramBot.downloadFileStreamAllocator(
filePath: String
) = execute(DownloadFileStream(filePath))
suspend fun TelegramBot.downloadFileStreamAllocator(
pathedFile: PathedFile
) = downloadFileStreamAllocator(pathedFile.filePath)
suspend fun TelegramBot.downloadFileStreamAllocator(
fileId: FileId
) = downloadFileStreamAllocator(getFileAdditionalInfo(fileId))
suspend fun TelegramBot.downloadFileStreamAllocator(
file: TelegramMediaFile
) = downloadFileStreamAllocator(getFileAdditionalInfo(file))
suspend fun TelegramBot.downloadFileStreamAllocator(
file: MediaContent
) = downloadFileStreamAllocator(getFileAdditionalInfo(file.media))

View File

@ -4,6 +4,7 @@ import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.abstracts.FileId import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.get.GetFile import dev.inmo.tgbotapi.requests.get.GetFile
import dev.inmo.tgbotapi.types.files.abstracts.TelegramMediaFile import dev.inmo.tgbotapi.types.files.abstracts.TelegramMediaFile
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
suspend fun TelegramBot.getFileAdditionalInfo( suspend fun TelegramBot.getFileAdditionalInfo(
fileId: FileId fileId: FileId
@ -14,3 +15,7 @@ suspend fun TelegramBot.getFileAdditionalInfo(
suspend fun TelegramBot.getFileAdditionalInfo( suspend fun TelegramBot.getFileAdditionalInfo(
file: TelegramMediaFile file: TelegramMediaFile
) = getFileAdditionalInfo(file.fileId) ) = getFileAdditionalInfo(file.fileId)
suspend fun TelegramBot.getFileAdditionalInfo(
content: MediaContent
) = getFileAdditionalInfo(content.media)

View File

@ -0,0 +1,64 @@
package dev.inmo.tgbotapi.extensions.api.files
import dev.inmo.micro_utils.coroutines.doOutsideOfCoroutine
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.api.get.getFileAdditionalInfo
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.types.files.PathedFile
import dev.inmo.tgbotapi.types.files.abstracts.TelegramMediaFile
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
import io.ktor.util.cio.use
import io.ktor.util.cio.writeChannel
import io.ktor.utils.io.copyTo
import kotlinx.coroutines.job
import java.io.File
import kotlin.coroutines.coroutineContext
suspend fun TelegramBot.downloadFile(
filePath: String,
destFile: File
): File {
val readChannel = downloadFileStream(filePath)
destFile.deleteRecursively()
destFile.parentFile.mkdirs()
doOutsideOfCoroutine { destFile.createNewFile() }
destFile.writeChannel(coroutineContext.job).use {
readChannel.copyTo(this)
}
return destFile
}
suspend fun TelegramBot.downloadFile(
pathedFile: PathedFile,
destFile: File
) = downloadFile(
pathedFile.filePath,
destFile
)
suspend fun TelegramBot.downloadFile(
fileId: FileId,
destFile: File
) = downloadFile(
getFileAdditionalInfo(fileId),
destFile
)
suspend fun TelegramBot.downloadFile(
file: TelegramMediaFile,
destFile: File
): File = downloadFile(
getFileAdditionalInfo(file),
destFile
)
suspend fun TelegramBot.downloadFile(
file: MediaContent,
destFile: File
) = downloadFile(
getFileAdditionalInfo(file.media),
destFile
)

View File

@ -0,0 +1,38 @@
package dev.inmo.tgbotapi.extensions.utils.types.files
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.DownloadFileStream
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.get.GetFile
import dev.inmo.tgbotapi.types.files.PathedFile
import dev.inmo.tgbotapi.types.files.abstracts.TelegramMediaFile
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
import dev.inmo.tgbotapi.utils.*
suspend fun convertToStorageFile(
downloadStreamAllocator: ByteReadChannelAllocator,
pathedFile: PathedFile
): StorageFile {
return downloadStreamAllocator.asStorageFile(
pathedFile.fileName
)
}
suspend fun TelegramBot.convertToStorageFile(
pathedFile: PathedFile
): StorageFile = convertToStorageFile(
execute(DownloadFileStream(pathedFile.filePath)),
pathedFile
)
suspend fun TelegramBot.convertToStorageFile(
fileId: FileId
): StorageFile = convertToStorageFile(execute(GetFile(fileId)))
suspend fun TelegramBot.convertToStorageFile(
file: TelegramMediaFile
): StorageFile = convertToStorageFile(file.fileId)
suspend fun TelegramBot.convertToStorageFile(
content: MediaContent
): StorageFile = convertToStorageFile(content.media)

View File

@ -9,6 +9,7 @@ fun PathedFile.asStream(
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper
): InputStream = URL(this.fullUrl(telegramAPIUrlsKeeper)).openStream() ): InputStream = URL(this.fullUrl(telegramAPIUrlsKeeper)).openStream()
@Deprecated("This api will be removed soon. Use `downloadFile` instead")
fun PathedFile.asFile( fun PathedFile.asFile(
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper, telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper,
dest: File = File.createTempFile(this.fileUniqueId, this.filename), dest: File = File.createTempFile(this.fileUniqueId, this.filename),
@ -22,6 +23,7 @@ fun PathedFile.asFile(
return dest return dest
} }
@Deprecated("This api will be removed soon. Use `downloadFile` instead")
fun PathedFile.asBytes( fun PathedFile.asBytes(
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper
): ByteArray = this.asStream(telegramAPIUrlsKeeper) ): ByteArray = this.asStream(telegramAPIUrlsKeeper)