1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2026-09-15 12:34:37 +00:00

Complete Bot API 10.3 ephemeral media support

This commit is contained in:
2026-08-26 15:27:04 +06:00
parent d972cc5b8d
commit f8e70c5cc7
10 changed files with 329 additions and 24 deletions

View File

@@ -20,6 +20,7 @@ import dev.inmo.tgbotapi.types.message.abstracts.ChatContentMessage
import dev.inmo.tgbotapi.types.message.content.* import dev.inmo.tgbotapi.types.message.content.*
import dev.inmo.tgbotapi.types.message.textsources.TextSource import dev.inmo.tgbotapi.types.message.textsources.TextSource
import dev.inmo.tgbotapi.types.polls.PollOptionPersistentId import dev.inmo.tgbotapi.types.polls.PollOptionPersistentId
import dev.inmo.tgbotapi.types.rich.InputRichMessage
import dev.inmo.tgbotapi.types.venue.Venue import dev.inmo.tgbotapi.types.venue.Venue
import dev.inmo.tgbotapi.utils.* import dev.inmo.tgbotapi.utils.*
import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmMultifileClass
@@ -27,9 +28,83 @@ import kotlin.jvm.JvmName
// Ephemeral-only replies // Ephemeral-only replies
// //
// Every overload requires replyInChatId, ephemeralMessageParameters.receiverUserId, and replyToEphemeralMessageId because no // Every overload requires replyInChatId, an EphemeralMessageParameters object, and replyToEphemeralMessageId because no
// source message supplies ephemeral reply routing. // source message supplies ephemeral reply routing.
public suspend inline fun TelegramBot.replyRichMessage(
replyInChatId: IdChatIdentifier,
ephemeralMessageParameters: EphemeralMessageParameters,
replyToEphemeralMessageId: EphemeralMessageId,
richMessage: InputRichMessage,
replyInThreadId: MessageThreadId? = replyInChatId.threadId,
replyInDirectMessageThreadId: DirectMessageThreadId? = replyInChatId.directMessageThreadId,
replyInBusinessConnectionId: BusinessConnectionId? = replyInChatId.businessConnectionId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
effectId: EffectId? = null,
suggestedPostParameters: SuggestedPostParameters? = null,
allowSendingWithoutReply: Boolean? = null,
checklistTaskId: ChecklistTaskId? = null,
pollOptionId: PollOptionPersistentId? = null,
replyMarkup: KeyboardMarkup? = null
): ChatContentMessage<RichMessageContent> = sendRichMessage(
chatId = replyInChatId,
richMessage = richMessage,
threadId = replyInThreadId,
directMessageThreadId = replyInDirectMessageThreadId,
businessConnectionId = replyInBusinessConnectionId,
ephemeralMessageParameters = ephemeralMessageParameters,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
effectId = effectId,
suggestedPostParameters = suggestedPostParameters,
replyParameters = ReplyParameters(
ephemeralMessageId = replyToEphemeralMessageId,
allowSendingWithoutReply = allowSendingWithoutReply,
checklistTaskId = checklistTaskId,
pollOptionId = pollOptionId
),
replyMarkup = replyMarkup
)
public suspend inline fun TelegramBot.reply(
replyInChatId: IdChatIdentifier,
ephemeralMessageParameters: EphemeralMessageParameters,
replyToEphemeralMessageId: EphemeralMessageId,
richMessage: InputRichMessage,
replyInThreadId: MessageThreadId? = replyInChatId.threadId,
replyInDirectMessageThreadId: DirectMessageThreadId? = replyInChatId.directMessageThreadId,
replyInBusinessConnectionId: BusinessConnectionId? = replyInChatId.businessConnectionId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
effectId: EffectId? = null,
suggestedPostParameters: SuggestedPostParameters? = null,
allowSendingWithoutReply: Boolean? = null,
checklistTaskId: ChecklistTaskId? = null,
pollOptionId: PollOptionPersistentId? = null,
replyMarkup: KeyboardMarkup? = null
): ChatContentMessage<RichMessageContent> = replyRichMessage(
replyInChatId = replyInChatId,
ephemeralMessageParameters = ephemeralMessageParameters,
replyToEphemeralMessageId = replyToEphemeralMessageId,
richMessage = richMessage,
replyInThreadId = replyInThreadId,
replyInDirectMessageThreadId = replyInDirectMessageThreadId,
replyInBusinessConnectionId = replyInBusinessConnectionId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
effectId = effectId,
suggestedPostParameters = suggestedPostParameters,
allowSendingWithoutReply = allowSendingWithoutReply,
checklistTaskId = checklistTaskId,
pollOptionId = pollOptionId,
replyMarkup = replyMarkup
)
public suspend inline fun TelegramBot.reply( public suspend inline fun TelegramBot.reply(
replyInChatId: IdChatIdentifier, replyInChatId: IdChatIdentifier,
ephemeralMessageParameters: EphemeralMessageParameters, ephemeralMessageParameters: EphemeralMessageParameters,

View File

@@ -8,22 +8,167 @@ import dev.inmo.tgbotapi.requests.abstracts.InputFile
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.message.ParseMode import dev.inmo.tgbotapi.types.message.ParseMode
import dev.inmo.tgbotapi.types.message.SuggestedPostParameters
import dev.inmo.tgbotapi.types.message.abstracts.ChatContentMessage import dev.inmo.tgbotapi.types.message.abstracts.ChatContentMessage
import dev.inmo.tgbotapi.types.message.content.* import dev.inmo.tgbotapi.types.message.content.*
import dev.inmo.tgbotapi.types.business_connection.BusinessConnectionId
import dev.inmo.tgbotapi.types.checklists.ChecklistTaskId
import dev.inmo.tgbotapi.types.polls.PollOptionPersistentId
import dev.inmo.tgbotapi.types.rich.InputRichMessage
/** /**
* Explicit helpers replying directly to an incoming ephemeral message identified by [chatId]/[ephemeralMessageId] * Explicit helpers replying directly to an incoming ephemeral message identified by [chatId]/[ephemeralMessageId]
* (as opposed to the `reply(to = someMessage, ...)` smart-branch overloads, which detect an ephemeral * (as opposed to the `reply(to = someMessage, ...)` smart-branch overloads, which detect an ephemeral
* [dev.inmo.tgbotapi.types.message.abstracts.PossiblyEphemeralMessage] target automatically). The outgoing message * [dev.inmo.tgbotapi.types.message.abstracts.PossiblyEphemeralMessage] target automatically). The outgoing message
* is itself sent as ephemeral, addressed to the same [ephemeralMessageParameters.receiverUserId] as the message being replied to. * is itself sent as ephemeral according to [ephemeralMessageParameters] and replies to [ephemeralMessageId].
* *
* Each helper has two forms: one taking explicit `ephemeralMessageParameters.receiverUserId`/`ephemeralMessageId`, and a convenience overload * Each helper has two forms: one taking an explicit [EphemeralMessageParameters] object plus [EphemeralMessageId], and a convenience overload
* taking an [dev.inmo.tgbotapi.types.EphemeralChatId] which sources both from the identifier (throwing * taking an [dev.inmo.tgbotapi.types.EphemeralChatId] which sources the parameter object plus message identifier (throwing
* [IllegalArgumentException] if it does not carry an `ephemeralMessageId`). * [IllegalArgumentException] if it does not carry an `ephemeralMessageId`).
* *
* @see dev.inmo.tgbotapi.types.ephemeralReplyParametersOrNull * @see dev.inmo.tgbotapi.types.ephemeralReplyParametersOrNull
*/ */
public suspend fun TelegramBot.replyToEphemeralRichMessage(
chatId: ChatIdentifier,
ephemeralMessageParameters: EphemeralMessageParameters,
ephemeralMessageId: EphemeralMessageId,
richMessage: InputRichMessage,
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
effectId: EffectId? = null,
suggestedPostParameters: SuggestedPostParameters? = null,
allowSendingWithoutReply: Boolean? = null,
checklistTaskId: ChecklistTaskId? = null,
pollOptionId: PollOptionPersistentId? = null,
replyMarkup: KeyboardMarkup? = null
): ChatContentMessage<RichMessageContent> = sendRichMessage(
chatId = chatId,
richMessage = richMessage,
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
ephemeralMessageParameters = ephemeralMessageParameters,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
effectId = effectId,
suggestedPostParameters = suggestedPostParameters,
replyParameters = ReplyParameters(
ephemeralMessageId = ephemeralMessageId,
allowSendingWithoutReply = allowSendingWithoutReply,
checklistTaskId = checklistTaskId,
pollOptionId = pollOptionId
),
replyMarkup = replyMarkup
)
public suspend fun TelegramBot.replyToEphemeralRichMessage(
chatId: EphemeralChatId,
richMessage: InputRichMessage,
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
effectId: EffectId? = null,
suggestedPostParameters: SuggestedPostParameters? = null,
allowSendingWithoutReply: Boolean? = null,
checklistTaskId: ChecklistTaskId? = null,
pollOptionId: PollOptionPersistentId? = null,
replyMarkup: KeyboardMarkup? = null
): ChatContentMessage<RichMessageContent> = replyToEphemeralRichMessage(
chatId = chatId,
ephemeralMessageParameters = EphemeralMessageParameters(chatId.receiverUser),
ephemeralMessageId = requireNotNull(chatId.ephemeralMessageId) { "chatId ($chatId) does not carry an ephemeralMessageId" },
richMessage = richMessage,
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
effectId = effectId,
suggestedPostParameters = suggestedPostParameters,
allowSendingWithoutReply = allowSendingWithoutReply,
checklistTaskId = checklistTaskId,
pollOptionId = pollOptionId,
replyMarkup = replyMarkup
)
public suspend fun TelegramBot.replyToEphemeral(
chatId: ChatIdentifier,
ephemeralMessageParameters: EphemeralMessageParameters,
ephemeralMessageId: EphemeralMessageId,
richMessage: InputRichMessage,
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
effectId: EffectId? = null,
suggestedPostParameters: SuggestedPostParameters? = null,
allowSendingWithoutReply: Boolean? = null,
checklistTaskId: ChecklistTaskId? = null,
pollOptionId: PollOptionPersistentId? = null,
replyMarkup: KeyboardMarkup? = null
): ChatContentMessage<RichMessageContent> = replyToEphemeralRichMessage(
chatId = chatId,
ephemeralMessageParameters = ephemeralMessageParameters,
ephemeralMessageId = ephemeralMessageId,
richMessage = richMessage,
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
effectId = effectId,
suggestedPostParameters = suggestedPostParameters,
allowSendingWithoutReply = allowSendingWithoutReply,
checklistTaskId = checklistTaskId,
pollOptionId = pollOptionId,
replyMarkup = replyMarkup
)
public suspend fun TelegramBot.replyToEphemeral(
chatId: EphemeralChatId,
richMessage: InputRichMessage,
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
effectId: EffectId? = null,
suggestedPostParameters: SuggestedPostParameters? = null,
allowSendingWithoutReply: Boolean? = null,
checklistTaskId: ChecklistTaskId? = null,
pollOptionId: PollOptionPersistentId? = null,
replyMarkup: KeyboardMarkup? = null
): ChatContentMessage<RichMessageContent> = replyToEphemeralRichMessage(
chatId = chatId,
richMessage = richMessage,
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
effectId = effectId,
suggestedPostParameters = suggestedPostParameters,
allowSendingWithoutReply = allowSendingWithoutReply,
checklistTaskId = checklistTaskId,
pollOptionId = pollOptionId,
replyMarkup = replyMarkup
)
/** /**
* @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or * @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or
* [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard] as a builders for that param * [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard] as a builders for that param
@@ -46,7 +191,7 @@ public suspend fun TelegramBot.replyToEphemeral(
) )
/** /**
* Convenience overload sourcing `ephemeralMessageParameters.receiverUserId`/`ephemeralMessageId` from [chatId]. Throws * Convenience overload sourcing an [EphemeralMessageParameters] object plus [EphemeralMessageId] from [chatId]. Throws
* [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId * [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId
* *
* @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or * @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or
@@ -88,7 +233,7 @@ public suspend fun TelegramBot.replyToEphemeralWithPhoto(
) )
/** /**
* Convenience overload sourcing `ephemeralMessageParameters.receiverUserId`/`ephemeralMessageId` from [chatId]. Throws * Convenience overload sourcing an [EphemeralMessageParameters] object plus [EphemeralMessageId] from [chatId]. Throws
* [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId * [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId
*/ */
public suspend fun TelegramBot.replyToEphemeralWithPhoto( public suspend fun TelegramBot.replyToEphemeralWithPhoto(
@@ -131,7 +276,7 @@ public suspend fun TelegramBot.replyToEphemeralWithLivePhoto(
) )
/** /**
* Convenience overload sourcing `ephemeralMessageParameters.receiverUserId`/`ephemeralMessageId` from [chatId]. Throws * Convenience overload sourcing an [EphemeralMessageParameters] object plus [EphemeralMessageId] from [chatId]. Throws
* [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId * [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId
*/ */
public suspend fun TelegramBot.replyToEphemeralWithLivePhoto( public suspend fun TelegramBot.replyToEphemeralWithLivePhoto(
@@ -174,7 +319,7 @@ public suspend fun TelegramBot.replyToEphemeralWithAudio(
) )
/** /**
* Convenience overload sourcing `ephemeralMessageParameters.receiverUserId`/`ephemeralMessageId` from [chatId]. Throws * Convenience overload sourcing an [EphemeralMessageParameters] object plus [EphemeralMessageId] from [chatId]. Throws
* [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId * [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId
*/ */
public suspend fun TelegramBot.replyToEphemeralWithAudio( public suspend fun TelegramBot.replyToEphemeralWithAudio(
@@ -215,7 +360,7 @@ public suspend fun TelegramBot.replyToEphemeralWithDocument(
) )
/** /**
* Convenience overload sourcing `ephemeralMessageParameters.receiverUserId`/`ephemeralMessageId` from [chatId]. Throws * Convenience overload sourcing an [EphemeralMessageParameters] object plus [EphemeralMessageId] from [chatId]. Throws
* [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId * [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId
*/ */
public suspend fun TelegramBot.replyToEphemeralWithDocument( public suspend fun TelegramBot.replyToEphemeralWithDocument(
@@ -256,7 +401,7 @@ public suspend fun TelegramBot.replyToEphemeralWithVideo(
) )
/** /**
* Convenience overload sourcing `ephemeralMessageParameters.receiverUserId`/`ephemeralMessageId` from [chatId]. Throws * Convenience overload sourcing an [EphemeralMessageParameters] object plus [EphemeralMessageId] from [chatId]. Throws
* [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId * [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId
*/ */
public suspend fun TelegramBot.replyToEphemeralWithVideo( public suspend fun TelegramBot.replyToEphemeralWithVideo(
@@ -297,7 +442,7 @@ public suspend fun TelegramBot.replyToEphemeralWithAnimation(
) )
/** /**
* Convenience overload sourcing `ephemeralMessageParameters.receiverUserId`/`ephemeralMessageId` from [chatId]. Throws * Convenience overload sourcing an [EphemeralMessageParameters] object plus [EphemeralMessageId] from [chatId]. Throws
* [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId * [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId
*/ */
public suspend fun TelegramBot.replyToEphemeralWithAnimation( public suspend fun TelegramBot.replyToEphemeralWithAnimation(
@@ -338,7 +483,7 @@ public suspend fun TelegramBot.replyToEphemeralWithVoice(
) )
/** /**
* Convenience overload sourcing `ephemeralMessageParameters.receiverUserId`/`ephemeralMessageId` from [chatId]. Throws * Convenience overload sourcing an [EphemeralMessageParameters] object plus [EphemeralMessageId] from [chatId]. Throws
* [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId * [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId
*/ */
public suspend fun TelegramBot.replyToEphemeralWithVoice( public suspend fun TelegramBot.replyToEphemeralWithVoice(
@@ -375,7 +520,7 @@ public suspend fun TelegramBot.replyToEphemeralWithVideoNote(
) )
/** /**
* Convenience overload sourcing `ephemeralMessageParameters.receiverUserId`/`ephemeralMessageId` from [chatId]. Throws * Convenience overload sourcing an [EphemeralMessageParameters] object plus [EphemeralMessageId] from [chatId]. Throws
* [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId * [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId
*/ */
public suspend fun TelegramBot.replyToEphemeralWithVideoNote( public suspend fun TelegramBot.replyToEphemeralWithVideoNote(
@@ -408,7 +553,7 @@ public suspend fun TelegramBot.replyToEphemeralWithSticker(
) )
/** /**
* Convenience overload sourcing `ephemeralMessageParameters.receiverUserId`/`ephemeralMessageId` from [chatId]. Throws * Convenience overload sourcing an [EphemeralMessageParameters] object plus [EphemeralMessageId] from [chatId]. Throws
* [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId * [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId
*/ */
public suspend fun TelegramBot.replyToEphemeralWithSticker( public suspend fun TelegramBot.replyToEphemeralWithSticker(
@@ -447,7 +592,7 @@ public suspend fun TelegramBot.replyToEphemeralWithLocation(
/** /**
* Sends a static location (`live_period` is not supported for ephemeral messages, see [SendLocation.Live]). * Sends a static location (`live_period` is not supported for ephemeral messages, see [SendLocation.Live]).
* Convenience overload sourcing `ephemeralMessageParameters.receiverUserId`/`ephemeralMessageId` from [chatId]. Throws * Convenience overload sourcing an [EphemeralMessageParameters] object plus [EphemeralMessageId] from [chatId]. Throws
* [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId * [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId
*/ */
public suspend fun TelegramBot.replyToEphemeralWithLocation( public suspend fun TelegramBot.replyToEphemeralWithLocation(
@@ -488,7 +633,7 @@ public suspend fun TelegramBot.replyToEphemeralWithVenue(
) )
/** /**
* Convenience overload sourcing `ephemeralMessageParameters.receiverUserId`/`ephemeralMessageId` from [chatId]. Throws * Convenience overload sourcing an [EphemeralMessageParameters] object plus [EphemeralMessageId] from [chatId]. Throws
* [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId * [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId
*/ */
public suspend fun TelegramBot.replyToEphemeralWithVenue( public suspend fun TelegramBot.replyToEphemeralWithVenue(
@@ -531,7 +676,7 @@ public suspend fun TelegramBot.replyToEphemeralWithContact(
) )
/** /**
* Convenience overload sourcing `ephemeralMessageParameters.receiverUserId`/`ephemeralMessageId` from [chatId]. Throws * Convenience overload sourcing an [EphemeralMessageParameters] object plus [EphemeralMessageId] from [chatId]. Throws
* [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId * [IllegalArgumentException] if [chatId] does not carry an ephemeralMessageId
*/ */
public suspend fun TelegramBot.replyToEphemeralWithContact( public suspend fun TelegramBot.replyToEphemeralWithContact(

View File

@@ -6,7 +6,10 @@ import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.requests.edit.abstracts.* import dev.inmo.tgbotapi.requests.edit.abstracts.*
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.business_connection.BusinessConnectionId import dev.inmo.tgbotapi.types.business_connection.BusinessConnectionId
import dev.inmo.tgbotapi.types.media.CoveredTelegramMedia
import dev.inmo.tgbotapi.types.media.PhotoedTelegramMedia
import dev.inmo.tgbotapi.types.media.TelegramFreeMedia import dev.inmo.tgbotapi.types.media.TelegramFreeMedia
import dev.inmo.tgbotapi.types.media.ThumbedTelegramMedia
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
@@ -34,9 +37,12 @@ data class EditChatMessageMedia(
override val data: SimpleRequest<ContentMessage<MediaContent>> override val data: SimpleRequest<ContentMessage<MediaContent>>
get() = this get() = this
override val mediaMap: Map<String, MultipartFile> by lazy { override val mediaMap: Map<String, MultipartFile> by lazy {
(media.file as? MultipartFile) ?.let { listOfNotNull(
mapOf(it.fileId to it) media.file as? MultipartFile,
} ?: emptyMap() (media as? PhotoedTelegramMedia) ?.photo as? MultipartFile,
(media as? ThumbedTelegramMedia) ?.thumb as? MultipartFile,
(media as? CoveredTelegramMedia) ?.cover as? MultipartFile
).associateBy { it.fileId }
} }
// init { // init {

View File

@@ -6,6 +6,7 @@ import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.requests.edit.abstracts.* import dev.inmo.tgbotapi.requests.edit.abstracts.*
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.media.CoveredTelegramMedia import dev.inmo.tgbotapi.types.media.CoveredTelegramMedia
import dev.inmo.tgbotapi.types.media.PhotoedTelegramMedia
import dev.inmo.tgbotapi.types.media.TelegramFreeMedia import dev.inmo.tgbotapi.types.media.TelegramFreeMedia
import dev.inmo.tgbotapi.types.media.ThumbedTelegramMedia import dev.inmo.tgbotapi.types.media.ThumbedTelegramMedia
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
@@ -48,6 +49,7 @@ data class EditEphemeralMessageMedia(
override val mediaMap: Map<String, MultipartFile> by lazy { override val mediaMap: Map<String, MultipartFile> by lazy {
listOfNotNull( listOfNotNull(
media.file as? MultipartFile, media.file as? MultipartFile,
(media as? PhotoedTelegramMedia) ?.photo as? MultipartFile,
(media as? ThumbedTelegramMedia) ?.thumb as? MultipartFile, (media as? ThumbedTelegramMedia) ?.thumb as? MultipartFile,
(media as? CoveredTelegramMedia) ?.cover as? MultipartFile (media as? CoveredTelegramMedia) ?.cover as? MultipartFile
).associateBy { it.fileId } ).associateBy { it.fileId }

View File

@@ -53,6 +53,11 @@ fun <T : MediaGroupPartContent> SendMediaGroup(
val files: List<MultipartFile> = media.flatMap { val files: List<MultipartFile> = media.flatMap {
listOfNotNull( listOfNotNull(
it.file as? MultipartFile, it.file as? MultipartFile,
if (it is PhotoedTelegramMedia) {
it.photo as? MultipartFile
} else {
null
},
if (it is ThumbedTelegramMedia) { if (it is ThumbedTelegramMedia) {
it.thumb as? MultipartFile it.thumb as? MultipartFile
} else { } else {

View File

@@ -15,6 +15,7 @@ import dev.inmo.tgbotapi.types.message.ParseMode
import dev.inmo.tgbotapi.types.message.parseModeField import dev.inmo.tgbotapi.types.message.parseModeField
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.media.CoveredTelegramMedia import dev.inmo.tgbotapi.types.media.CoveredTelegramMedia
import dev.inmo.tgbotapi.types.media.PhotoedTelegramMedia
import dev.inmo.tgbotapi.types.media.ThumbedTelegramMedia import dev.inmo.tgbotapi.types.media.ThumbedTelegramMedia
import dev.inmo.tgbotapi.types.message.* import dev.inmo.tgbotapi.types.message.*
import dev.inmo.tgbotapi.types.message.RawMessageEntity import dev.inmo.tgbotapi.types.message.RawMessageEntity
@@ -67,6 +68,11 @@ fun SendPaidMedia(
val files: List<MultipartFile> = media.flatMap { val files: List<MultipartFile> = media.flatMap {
listOfNotNull( listOfNotNull(
it.file as? MultipartFile, it.file as? MultipartFile,
if (it is PhotoedTelegramMedia) {
it.photo as? MultipartFile
} else {
null
},
if (it is ThumbedTelegramMedia) { if (it is ThumbedTelegramMedia) {
it.thumb as? MultipartFile it.thumb as? MultipartFile
} else { } else {
@@ -130,6 +136,11 @@ fun SendPaidMedia(
val files: List<MultipartFile> = media.flatMap { val files: List<MultipartFile> = media.flatMap {
listOfNotNull( listOfNotNull(
it.file as? MultipartFile, it.file as? MultipartFile,
if (it is PhotoedTelegramMedia) {
it.photo as? MultipartFile
} else {
null
},
if (it is ThumbedTelegramMedia) { if (it is ThumbedTelegramMedia) {
it.thumb as? MultipartFile it.thumb as? MultipartFile
} else { } else {

View File

@@ -0,0 +1,7 @@
package dev.inmo.tgbotapi.types.media
import dev.inmo.tgbotapi.requests.abstracts.InputFile
sealed interface PhotoedTelegramMedia : TelegramMedia {
val photo: InputFile
}

View File

@@ -50,7 +50,7 @@ fun TelegramMediaLivePhoto(
data class TelegramMediaLivePhoto internal constructor( data class TelegramMediaLivePhoto internal constructor(
override val file: InputFile, override val file: InputFile,
@SerialName(photoField) @SerialName(photoField)
val photo: InputFile, override val photo: InputFile,
@SerialName(captionField) @SerialName(captionField)
override val text: String? = null, override val text: String? = null,
@SerialName(parseModeField) @SerialName(parseModeField)
@@ -64,7 +64,8 @@ data class TelegramMediaLivePhoto internal constructor(
) : TelegramFreeMedia, ) : TelegramFreeMedia,
VisualMediaGroupMemberTelegramMedia, VisualMediaGroupMemberTelegramMedia,
InputPollMedia, InputPollMedia,
InputPollOptionMedia { InputPollOptionMedia,
PhotoedTelegramMedia {
@EncodeDefault @EncodeDefault
override val type: String = TYPE override val type: String = TYPE
override val textSources: TextSourcesList? by lazy { override val textSources: TextSourcesList? by lazy {

View File

@@ -12,8 +12,8 @@ import kotlinx.serialization.*
data class TelegramPaidMediaLivePhoto( data class TelegramPaidMediaLivePhoto(
override val file: InputFile, override val file: InputFile,
@SerialName(photoField) @SerialName(photoField)
val photo: InputFile, override val photo: InputFile,
) : VisualTelegramPaidMedia { ) : VisualTelegramPaidMedia, PhotoedTelegramMedia {
override val type: String = TYPE override val type: String = TYPE
@SerialName(mediaField) @SerialName(mediaField)

View File

@@ -3,22 +3,30 @@ package dev.inmo.tgbotapi.types
import dev.inmo.tgbotapi.requests.send.SendTextMessage import dev.inmo.tgbotapi.requests.send.SendTextMessage
import dev.inmo.tgbotapi.requests.abstracts.asMultipartFile import dev.inmo.tgbotapi.requests.abstracts.asMultipartFile
import dev.inmo.tgbotapi.requests.abstracts.json import dev.inmo.tgbotapi.requests.abstracts.json
import dev.inmo.tgbotapi.requests.abstracts.MultipartRequest
import dev.inmo.tgbotapi.requests.chat.members.PromoteChatMember import dev.inmo.tgbotapi.requests.chat.members.PromoteChatMember
import dev.inmo.tgbotapi.requests.edit.caption.EditEphemeralMessageCaption import dev.inmo.tgbotapi.requests.edit.caption.EditEphemeralMessageCaption
import dev.inmo.tgbotapi.requests.edit.media.EditChatMessageMedia
import dev.inmo.tgbotapi.requests.edit.media.EditEphemeralMessageMedia import dev.inmo.tgbotapi.requests.edit.media.EditEphemeralMessageMedia
import dev.inmo.tgbotapi.requests.edit.text.EditEphemeralMessageRichText import dev.inmo.tgbotapi.requests.edit.text.EditEphemeralMessageRichText
import dev.inmo.tgbotapi.requests.edit.text.EditEphemeralMessageText import dev.inmo.tgbotapi.requests.edit.text.EditEphemeralMessageText
import dev.inmo.tgbotapi.requests.send.media.SendPaidMedia
import dev.inmo.tgbotapi.requests.send.media.SendVisualMediaGroup
import dev.inmo.tgbotapi.types.chat.member.ChatCommonAdministratorRights import dev.inmo.tgbotapi.types.chat.member.ChatCommonAdministratorRights
import dev.inmo.tgbotapi.types.media.TelegramMediaPhoto import dev.inmo.tgbotapi.types.media.TelegramMediaPhoto
import dev.inmo.tgbotapi.types.media.TelegramMediaLivePhoto
import dev.inmo.tgbotapi.types.media.TelegramPaidMediaLivePhoto
import dev.inmo.tgbotapi.types.media.TelegramMediaVideo import dev.inmo.tgbotapi.types.media.TelegramMediaVideo
import dev.inmo.tgbotapi.types.rich.InputRichMessageHTML import dev.inmo.tgbotapi.types.rich.InputRichMessageHTML
import dev.inmo.tgbotapi.types.rich.InputRichMessageMedia import dev.inmo.tgbotapi.types.rich.InputRichMessageMedia
import dev.inmo.tgbotapi.utils.RiskFeature
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.jsonObject
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertFailsWith import kotlin.test.assertFailsWith
import kotlin.test.assertFalse import kotlin.test.assertFalse
import kotlin.test.assertIs
class EphemeralMessageParametersTest { class EphemeralMessageParametersTest {
private val json = Json { encodeDefaults = true } private val json = Json { encodeDefaults = true }
@@ -62,6 +70,51 @@ class EphemeralMessageParametersTest {
assertEquals(setOf(media.file.fileId), request.mediaMap.keys) assertEquals(setOf(media.file.fileId), request.mediaMap.keys)
} }
@Test
fun `EditEphemeralMessageMedia includes live photo and static photo multipart files`() {
val media = TelegramMediaLivePhoto(
file = "live photo".encodeToByteArray().asMultipartFile("live-photo.mov"),
photo = "static photo".encodeToByteArray().asMultipartFile("photo.jpg")
)
val request = EditEphemeralMessageMedia(ChatId(RawChatId(1L)), ChatId(RawChatId(2L)), EphemeralMessageId(3L), media)
assertEquals(setOf(media.file.fileId, media.photo.fileId), request.mediaMap.keys)
}
@Test
fun `EditChatMessageMedia includes live photo and static photo multipart files`() {
val media = TelegramMediaLivePhoto(
file = "live photo".encodeToByteArray().asMultipartFile("live-photo.mov"),
photo = "static photo".encodeToByteArray().asMultipartFile("photo.jpg")
)
val request = EditChatMessageMedia(ChatId(RawChatId(1L)), MessageId(3L), media)
assertEquals(setOf(media.file.fileId, media.photo.fileId), request.mediaMap.keys)
}
@OptIn(RiskFeature::class)
@Test
fun `SendVisualMediaGroup includes live photo and static photo multipart files`() {
val media = TelegramMediaLivePhoto(
file = "live photo".encodeToByteArray().asMultipartFile("live-photo.mov"),
photo = "static photo".encodeToByteArray().asMultipartFile("photo.jpg")
)
val request = SendVisualMediaGroup(ChatId(RawChatId(1L)), listOf(media, media))
assertEquals(setOf(media.file.fileId, media.photo.fileId), assertIs<MultipartRequest<*>>(request).mediaMap.keys)
}
@Test
fun `SendPaidMedia includes live photo and static photo multipart files`() {
val media = TelegramPaidMediaLivePhoto(
file = "live photo".encodeToByteArray().asMultipartFile("live-photo.mov"),
photo = "static photo".encodeToByteArray().asMultipartFile("photo.jpg")
)
val request = SendPaidMedia(ChatId(RawChatId(1L)), 1, listOf(media))
assertEquals(setOf(media.file.fileId, media.photo.fileId), assertIs<MultipartRequest<*>>(request).mediaMap.keys)
}
@Test @Test
fun `EditEphemeralMessageMedia includes multipart thumbnail and cover`() { fun `EditEphemeralMessageMedia includes multipart thumbnail and cover`() {
val video = TelegramMediaVideo( val video = TelegramMediaVideo(