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:
@@ -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,
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 }
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package dev.inmo.tgbotapi.types.media
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.requests.abstracts.InputFile
|
||||||
|
|
||||||
|
sealed interface PhotoedTelegramMedia : TelegramMedia {
|
||||||
|
val photo: InputFile
|
||||||
|
}
|
||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
Reference in New Issue
Block a user