This commit is contained in:
InsanusMokrassar 2022-04-21 17:54:15 +06:00
parent 8331d4edd7
commit b5334c2b72
12 changed files with 114 additions and 49 deletions

View File

@ -10,6 +10,10 @@ __All the `tgbotapi.extensions.*` packages have been removed__
* Constructor of `UnknownInlineKeyboardButton` is not internal and can be created with any `json` ([#563](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/563))
* All the interfaces from `dev.inmo.tgbotapi.types.files.abstracts` have been replaced to `dev.inmo.tgbotapi.types.files` and converted to sealed ([#550](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/550))
* `PassportFile` has been replaced to `dev.inmo.tgbotapi.types.files`
* `StorageFile` has been deprecated (fix of [#556](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/556))
* `MultipartFile` do not require `StorageFile` anymore
* `InputFile` companion got functions to simplify creation of `InputFile`s
* New typealias `FileUrl` (represents `FileId` but declare that they are the same)
* `WebApps`:
* Created 🎉
* `BehaviourBuilder`:

View File

@ -12,7 +12,7 @@ klock_version=2.7.0
uuid_version=0.4.0
ktor_version=1.6.8
micro_utils_version=0.9.20
micro_utils_version=0.9.24
javax_activation_version=1.1.1

View File

@ -55,6 +55,7 @@ kotlin {
api "dev.inmo:micro_utils.serialization.base64:$micro_utils_version"
api "dev.inmo:micro_utils.serialization.encapsulator:$micro_utils_version"
api "dev.inmo:micro_utils.serialization.typed_serializer:$micro_utils_version"
api "dev.inmo:micro_utils.ktor.common:$micro_utils_version"
api "dev.inmo:micro_utils.language_codes:$micro_utils_version"
api "io.ktor:ktor-client-core:$ktor_version"

View File

@ -1,6 +1,5 @@
package dev.inmo.tgbotapi.bot.Ktor.base
import dev.inmo.tgbotapi.bot.Ktor.KtorCallFactory
import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import dev.inmo.tgbotapi.utils.mapWithCommonValues
@ -26,7 +25,7 @@ class MultipartRequestCallFactory : AbstractRequestCallFactory() {
Headers.build {
append(HttpHeaders.ContentDisposition, "filename=${value.filename}")
},
block = value.file::input
block = value::input
)
is FileId -> append(key, value.fileId)
else -> append(key, value.toString())

View File

@ -1,11 +1,12 @@
package dev.inmo.tgbotapi.requests.abstracts
import com.benasher44.uuid.uuid4
import dev.inmo.micro_utils.common.MPPFile
import dev.inmo.tgbotapi.utils.*
import io.ktor.utils.io.ByteReadChannel
import io.ktor.utils.io.core.ByteReadPacket
import io.ktor.utils.io.core.Input
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
@ -24,6 +25,15 @@ import kotlinx.serialization.encoding.Encoder
@Serializable(InputFileSerializer::class)
sealed class InputFile {
abstract val fileId: String
companion object {
operator fun invoke(file: MPPFile) = file.asMultipartFile()
fun fromInput(filename: String, inputSource: () -> Input) = MultipartFile(filename, inputSource)
fun fromFile(file: MPPFile) = invoke(file)
fun fromId(id: String) = FileId(id)
fun fromUrl(url: String) = FileUrl(url)
}
}
internal inline val InputFile.attachFileId
@ -43,6 +53,8 @@ data class FileId(
override val fileId: String
) : InputFile()
typealias FileUrl = FileId
fun String.toInputFile() = FileId(this)
@RiskFeature
@ -60,23 +72,49 @@ object InputFileSerializer : KSerializer<InputFile> {
*/
@Serializable(InputFileSerializer::class)
data class MultipartFile (
val file: StorageFile,
val filename: String = file.fileName
val filename: String,
private val inputSource: () -> Input
) : InputFile() {
override val fileId: String = file.generateCustomName()
@Required
override val fileId: String = "${uuid4()}.${filename.fileExtension}"
val input: Input
get() = inputSource()
@Deprecated("Storage file now is not necessary")
constructor(
file: StorageFile,
filename: String = file.fileName
) : this(
filename,
file::input
)
}
@Deprecated("Storage file now is not necessary")
@Suppress("NOTHING_TO_INLINE", "unused")
inline fun StorageFile.asMultipartFile() = MultipartFile(this)
inline fun StorageFile.asMultipartFile() = MultipartFile(fileName, ::input)
@Suppress("NOTHING_TO_INLINE", "unused")
suspend inline fun ByteReadChannel.asMultipartFile(
fileName: String
) = MultipartFile(asStorageFile(fileName))
) = MultipartFile(
fileName,
inputSource = asInput().let { { it } }
)
@Suppress("NOTHING_TO_INLINE", "unused")
inline fun ByteArray.asMultipartFile(
fileName: String
) = MultipartFile(
fileName,
inputSource = { ByteReadPacket(this) }
)
@Suppress("NOTHING_TO_INLINE", "unused")
suspend inline fun ByteReadChannelAllocator.asMultipartFile(
fileName: String
) = this.invoke().asMultipartFile(fileName)
expect suspend fun MPPFile.asMultipartFile(): MultipartFile
expect fun MPPFile.asMultipartFile(): MultipartFile
@Suppress("NOTHING_TO_INLINE")
inline fun MPPFile.multipartFile() = asMultipartFile()

View File

@ -8,23 +8,6 @@ import io.ktor.utils.io.core.ByteReadPacket
import io.ktor.utils.io.core.Input
import kotlinx.serialization.Serializable
/**
* Information about file for [StorageFile]
*
* @param contentType Raw type like "application/json"
* @param fileName This filename will be used in telegram system as name of file
*/
@Serializable
@Deprecated("Will be removed soon")
data class StorageFileInfo(
val fileName: String
) {
/**
* This methods is required for random generation of name for keeping warranties about unique file name
*/
fun generateCustomName() = "${uuid4()}.${fileName.fileExtension}"
}
/**
* Contains info about file, which potentially can be sent to telegram system.
*
@ -34,31 +17,22 @@ data class StorageFileInfo(
* @see StorageFileInfo
* @see asStorageFile
*/
@Deprecated("Storage file now is not necessary")
data class StorageFile(
val fileName: String,
private val inputSource: () -> Input
) {
val input: Input
get() = inputSource()
@Deprecated("This field will be removed soon. Use fileName instead of StorageFileInfo")
val storageFileInfo: StorageFileInfo
get() = StorageFileInfo(fileName)
/**
* This methods is required for random generation of name for keeping warranties about unique file name
*/
fun generateCustomName() = "${uuid4()}.${fileName.fileExtension}"
@Deprecated("This constructor will be removed soon. Use constructor with fileName instead of StorageFileInfo")
constructor(
storageFileInfo: StorageFileInfo,
inputSource: () -> Input
) : this(
storageFileInfo.fileName,
inputSource
)
}
@Deprecated("Storage file now is not necessary")
@Suppress("NOTHING_TO_INLINE")
inline fun StorageFile(
fileName: String,
@ -69,6 +43,7 @@ inline fun StorageFile(
ByteReadPacket(bytes)
}
@Deprecated("StorageFile now is not necessary")
@Suppress("NOTHING_TO_INLINE")
suspend inline fun StorageFile(
fileName: String,
@ -78,16 +53,19 @@ suspend inline fun StorageFile(
inputSource = byteReadChannel.asInput().let { { it } }
)
@Deprecated("StorageFile now is not necessary")
@Suppress("NOTHING_TO_INLINE", "unused")
inline fun ByteArray.asStorageFile(
fileName: String
) = StorageFile(fileName, this)
@Deprecated("StorageFile now is not necessary")
@Suppress("NOTHING_TO_INLINE", "unused")
suspend inline fun ByteReadChannel.asStorageFile(
fileName: String
) = StorageFile(fileName, this)
@Deprecated("StorageFile now is not necessary")
@Suppress("NOTHING_TO_INLINE", "unused")
suspend inline fun ByteReadChannelAllocator.asStorageFile(
fileName: String

View File

@ -3,6 +3,6 @@ package dev.inmo.tgbotapi.requests.abstracts
import dev.inmo.micro_utils.common.*
import io.ktor.utils.io.ByteReadChannel
actual suspend fun MPPFile.asMultipartFile(): MultipartFile = ByteReadChannel(bytes()).asMultipartFile(
actual fun MPPFile.asMultipartFile(): MultipartFile = bytesSync().asMultipartFile(
filename.name
)

View File

@ -1,12 +1,6 @@
package dev.inmo.tgbotapi.requests.abstracts
import dev.inmo.tgbotapi.utils.StorageFile
import java.io.File
fun File.toInputFile() = if (exists()) {
MultipartFile(
StorageFile(this)
)
} else {
error("Specified file $absolutePath does not exists")
}
@Deprecated("Duplacation of asMultipartFile", ReplaceWith("asMultipartFile", "dev.inmo.tgbotapi.requests.abstracts.asMultipartFile"))
fun File.toInputFile() = asMultipartFile()

View File

@ -1,5 +1,14 @@
package dev.inmo.tgbotapi.requests.abstracts
import dev.inmo.micro_utils.common.MPPFile
import dev.inmo.micro_utils.common.filename
import dev.inmo.micro_utils.ktor.common.input
actual suspend fun MPPFile.asMultipartFile(): MultipartFile = toInputFile()
actual fun MPPFile.asMultipartFile(): MultipartFile = if (exists()) {
MultipartFile(
filename.string,
::input
)
} else {
error("Specified file $absolutePath does not exists")
}

View File

@ -4,6 +4,7 @@ import io.ktor.utils.io.streams.asInput
import java.io.File
import java.nio.file.Files
@Deprecated("StorageFile now is not necessary")
fun StorageFile(
file: File
) = StorageFile(

View File

@ -0,0 +1,36 @@
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.*
import dev.inmo.tgbotapi.requests.get.GetFile
import dev.inmo.tgbotapi.types.files.PathedFile
import dev.inmo.tgbotapi.types.files.TelegramMediaFile
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
import dev.inmo.tgbotapi.utils.*
suspend fun multipartFile(
downloadStreamAllocator: ByteReadChannelAllocator,
pathedFile: PathedFile
): MultipartFile {
return downloadStreamAllocator.asMultipartFile(pathedFile.fileName)
}
suspend fun TelegramBot.multipartFile(
pathedFile: PathedFile
): MultipartFile = multipartFile(
execute(DownloadFileStream(pathedFile.filePath)),
pathedFile
)
suspend fun TelegramBot.multipartFile(
fileId: FileId
): MultipartFile = multipartFile(execute(GetFile(fileId)))
suspend fun TelegramBot.multipartFile(
file: TelegramMediaFile
): MultipartFile = multipartFile(file.fileId)
suspend fun TelegramBot.multipartFile(
content: MediaContent
): MultipartFile = multipartFile(content.media)

View File

@ -9,6 +9,7 @@ import dev.inmo.tgbotapi.types.files.TelegramMediaFile
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
import dev.inmo.tgbotapi.utils.*
@Deprecated("StorageFile now is not necessary")
suspend fun convertToStorageFile(
downloadStreamAllocator: ByteReadChannelAllocator,
pathedFile: PathedFile
@ -18,6 +19,7 @@ suspend fun convertToStorageFile(
)
}
@Deprecated("StorageFile now is not necessary")
suspend fun TelegramBot.convertToStorageFile(
pathedFile: PathedFile
): StorageFile = convertToStorageFile(
@ -25,14 +27,17 @@ suspend fun TelegramBot.convertToStorageFile(
pathedFile
)
@Deprecated("StorageFile now is not necessary")
suspend fun TelegramBot.convertToStorageFile(
fileId: FileId
): StorageFile = convertToStorageFile(execute(GetFile(fileId)))
@Deprecated("StorageFile now is not necessary")
suspend fun TelegramBot.convertToStorageFile(
file: TelegramMediaFile
): StorageFile = convertToStorageFile(file.fileId)
@Deprecated("StorageFile now is not necessary")
suspend fun TelegramBot.convertToStorageFile(
content: MediaContent
): StorageFile = convertToStorageFile(content.media)