1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2026-07-30 13:47:09 +00:00

Add Bot API 10.2 Ephemeral Messages support

New ephemeral messaging surface: EphemeralMessageId, Message.receiverUser/
ephemeralMessageId (PossiblyEphemeralMessage on group message impls),
BotCommand.isEphemeral, receiverUserId/callbackQueryId parameters across the 13
covered send methods (core requests, per-type api extensions and the
Sends/Replies/RepliesWithChatsAndMessages aggregators), editEphemeralMessageText/
Media/Caption/ReplyMarkup and deleteEphemeralMessage, plus replyToEphemeral
helpers and smart-branch ephemeral replies.

BREAKING: ReplyParameters.messageId and chatIdentifier are now nullable and the
WithMessageId supertype was dropped so ephemeral_message_id-only replies can be
expressed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-18 20:25:59 +06:00
parent 16be206b0f
commit 838caae7f5
57 changed files with 3571 additions and 801 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
package dev.inmo.tgbotapi.abstracts.types
import dev.inmo.tgbotapi.types.EphemeralMessageId
import dev.inmo.tgbotapi.types.UserId
interface EphemeralMessageAction : ChatRequest {
val receiverUserId: UserId
val ephemeralMessageId: EphemeralMessageId
}

View File

@@ -0,0 +1,25 @@
package dev.inmo.tgbotapi.requests
import dev.inmo.tgbotapi.abstracts.types.EphemeralMessageAction
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.utils.serializers.UnitFromBooleanSerializer
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
@Serializable
data class DeleteEphemeralMessage(
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
@SerialName(receiverUserIdField)
override val receiverUserId: UserId,
@SerialName(ephemeralMessageIdField)
override val ephemeralMessageId: EphemeralMessageId
) : SimpleRequest<Unit>, EphemeralMessageAction {
override fun method(): String = "deleteEphemeralMessage"
override val resultDeserializer: DeserializationStrategy<Unit>
get() = UnitFromBooleanSerializer
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -0,0 +1,12 @@
package dev.inmo.tgbotapi.requests.edit.abstracts
import dev.inmo.tgbotapi.abstracts.types.EphemeralMessageAction
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.utils.serializers.UnitFromBooleanSerializer
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.builtins.serializer
interface EditEphemeralMessage : SimpleRequest<Unit>, EphemeralMessageAction {
override val resultDeserializer: DeserializationStrategy<Unit>
get() = UnitFromBooleanSerializer
}

View File

@@ -0,0 +1,75 @@
package dev.inmo.tgbotapi.requests.edit.caption
import dev.inmo.tgbotapi.requests.edit.abstracts.*
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.message.textsources.TextSourcesList
import dev.inmo.tgbotapi.types.message.ParseMode
import dev.inmo.tgbotapi.types.message.parseModeField
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
import dev.inmo.tgbotapi.types.message.*
import dev.inmo.tgbotapi.types.message.RawMessageEntity
import dev.inmo.tgbotapi.types.message.toRawMessageEntities
import dev.inmo.tgbotapi.utils.extensions.makeString
import kotlinx.serialization.*
const val editEphemeralMessageCaptionMethod = "editEphemeralMessageCaption"
fun EditEphemeralMessageCaption(
chatId: ChatIdentifier,
receiverUserId: UserId,
ephemeralMessageId: EphemeralMessageId,
caption: String? = null,
parseMode: ParseMode? = null,
replyMarkup: InlineKeyboardMarkup? = null
) = EditEphemeralMessageCaption(
chatId = chatId,
receiverUserId = receiverUserId,
ephemeralMessageId = ephemeralMessageId,
text = caption,
parseMode = parseMode,
rawEntities = null,
replyMarkup = replyMarkup
)
fun EditEphemeralMessageCaption(
chatId: ChatIdentifier,
receiverUserId: UserId,
ephemeralMessageId: EphemeralMessageId,
entities: TextSourcesList,
replyMarkup: InlineKeyboardMarkup? = null
) = EditEphemeralMessageCaption(
chatId = chatId,
receiverUserId = receiverUserId,
ephemeralMessageId = ephemeralMessageId,
text = entities.makeString(),
parseMode = null,
rawEntities = entities.toRawMessageEntities(),
replyMarkup = replyMarkup
)
@ConsistentCopyVisibility
@Serializable
data class EditEphemeralMessageCaption internal constructor(
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
@SerialName(receiverUserIdField)
override val receiverUserId: UserId,
@SerialName(ephemeralMessageIdField)
override val ephemeralMessageId: EphemeralMessageId,
@SerialName(captionField)
override val text: String? = null,
@SerialName(parseModeField)
override val parseMode: ParseMode? = null,
@SerialName(captionEntitiesField)
private val rawEntities: List<RawMessageEntity>? = null,
@SerialName(replyMarkupField)
override val replyMarkup: InlineKeyboardMarkup? = null
) : EditEphemeralMessage, EditTextChatMessage, EditReplyMessage {
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text ?: return@lazy null)
}
override fun method(): String = editEphemeralMessageCaptionMethod
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -0,0 +1,36 @@
package dev.inmo.tgbotapi.requests.edit.media
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
import dev.inmo.tgbotapi.requests.edit.abstracts.*
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.media.TelegramFreeMedia
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
import kotlinx.serialization.*
const val editEphemeralMessageMediaMethod = "editEphemeralMessageMedia"
@Serializable
data class EditEphemeralMessageMedia(
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
@SerialName(receiverUserIdField)
override val receiverUserId: UserId,
@SerialName(ephemeralMessageIdField)
override val ephemeralMessageId: EphemeralMessageId,
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
@SerialName(mediaField)
override val media: TelegramFreeMedia,
@SerialName(replyMarkupField)
override val replyMarkup: InlineKeyboardMarkup? = null
) : EditEphemeralMessage, EditReplyMessage, EditMediaMessage {
init {
require(media.file !is MultipartFile) {
"For editing of ephemeral media messages you MUST use file id (uploading of a new file is not supported)"
}
}
override fun method(): String = editEphemeralMessageMediaMethod
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -0,0 +1,26 @@
package dev.inmo.tgbotapi.requests.edit.reply_markup
import dev.inmo.tgbotapi.requests.edit.abstracts.EditEphemeralMessage
import dev.inmo.tgbotapi.requests.edit.abstracts.EditReplyMessage
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
import kotlinx.serialization.*
const val editEphemeralMessageReplyMarkupMethod = "editEphemeralMessageReplyMarkup"
@Serializable
data class EditEphemeralMessageReplyMarkup(
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
@SerialName(receiverUserIdField)
override val receiverUserId: UserId,
@SerialName(ephemeralMessageIdField)
override val ephemeralMessageId: EphemeralMessageId,
@SerialName(replyMarkupField)
override val replyMarkup: InlineKeyboardMarkup? = null
) : EditEphemeralMessage, EditReplyMessage {
override fun method(): String = editEphemeralMessageReplyMarkupMethod
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -0,0 +1,88 @@
package dev.inmo.tgbotapi.requests.edit.text
import dev.inmo.tgbotapi.requests.edit.abstracts.*
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.message.textsources.TextSourcesList
import dev.inmo.tgbotapi.types.message.ParseMode
import dev.inmo.tgbotapi.types.message.parseModeField
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
import dev.inmo.tgbotapi.types.message.*
import dev.inmo.tgbotapi.types.message.RawMessageEntity
import dev.inmo.tgbotapi.types.message.toRawMessageEntities
import dev.inmo.tgbotapi.utils.extensions.makeString
import dev.inmo.tgbotapi.utils.throwRangeError
import kotlinx.serialization.*
const val editEphemeralMessageTextMethod = "editEphemeralMessageText"
fun EditEphemeralMessageText(
chatId: ChatIdentifier,
receiverUserId: UserId,
ephemeralMessageId: EphemeralMessageId,
text: String,
parseMode: ParseMode? = null,
linkPreviewOptions: LinkPreviewOptions? = null,
replyMarkup: InlineKeyboardMarkup? = null
) = EditEphemeralMessageText(
chatId = chatId,
receiverUserId = receiverUserId,
ephemeralMessageId = ephemeralMessageId,
text = text,
parseMode = parseMode,
rawEntities = null,
linkPreviewOptions = linkPreviewOptions,
replyMarkup = replyMarkup
)
fun EditEphemeralMessageText(
chatId: ChatIdentifier,
receiverUserId: UserId,
ephemeralMessageId: EphemeralMessageId,
entities: TextSourcesList,
linkPreviewOptions: LinkPreviewOptions? = null,
replyMarkup: InlineKeyboardMarkup? = null
) = EditEphemeralMessageText(
chatId = chatId,
receiverUserId = receiverUserId,
ephemeralMessageId = ephemeralMessageId,
text = entities.makeString(),
parseMode = null,
rawEntities = entities.toRawMessageEntities(),
linkPreviewOptions = linkPreviewOptions,
replyMarkup = replyMarkup
)
@ConsistentCopyVisibility
@Serializable
data class EditEphemeralMessageText internal constructor(
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
@SerialName(receiverUserIdField)
override val receiverUserId: UserId,
@SerialName(ephemeralMessageIdField)
override val ephemeralMessageId: EphemeralMessageId,
@SerialName(textField)
override val text: String,
@SerialName(parseModeField)
override val parseMode: ParseMode? = null,
@SerialName(entitiesField)
private val rawEntities: List<RawMessageEntity>? = null,
@SerialName(linkPreviewOptionsField)
override val linkPreviewOptions: LinkPreviewOptions? = null,
@SerialName(replyMarkupField)
override val replyMarkup: InlineKeyboardMarkup? = null
) : EditEphemeralMessage, EditTextChatMessage, EditReplyMessage, EditLinkPreviewOptionsContainer {
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text)
}
init {
if (text.length !in textLength) {
throwRangeError("Text length", textLength, text.length)
}
}
override fun method(): String = editEphemeralMessageTextMethod
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -1,5 +1,6 @@
package dev.inmo.tgbotapi.requests.send
import dev.inmo.tgbotapi.requests.send.abstracts.OptionallyEphemeralSendRequest
import dev.inmo.tgbotapi.requests.send.abstracts.ReplyingMarkupSendMessageRequest
import dev.inmo.tgbotapi.requests.send.abstracts.SendContentMessageRequest
import dev.inmo.tgbotapi.requests.send.abstracts.SendMessageRequest
@@ -36,6 +37,10 @@ data class SendContact(
override val directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
@SerialName(businessConnectionIdField)
override val businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
@SerialName(receiverUserIdField)
override val receiverUserId: UserId? = null,
@SerialName(callbackQueryIdField)
override val callbackQueryId: CallbackQueryId? = null,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(protectContentField)
@@ -51,7 +56,8 @@ data class SendContact(
@SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null
) : SendContentMessageRequest<ChatContentMessage<ContactContent>>,
ReplyingMarkupSendMessageRequest<ChatContentMessage<ContactContent>>
ReplyingMarkupSendMessageRequest<ChatContentMessage<ContactContent>>,
OptionallyEphemeralSendRequest
{
constructor(
chatId: ChatIdentifier,
@@ -59,6 +65,8 @@ data class SendContact(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
@@ -74,6 +82,8 @@ data class SendContact(
threadId,
directMessageThreadId,
businessConnectionId,
receiverUserId,
callbackQueryId,
disableNotification,
protectContent,
allowPaidBroadcast,
@@ -95,6 +105,8 @@ fun Contact.toRequest(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
@@ -108,6 +120,8 @@ fun Contact.toRequest(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,

View File

@@ -34,6 +34,8 @@ fun SendLocation(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
@@ -48,6 +50,8 @@ fun SendLocation(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
@@ -64,6 +68,8 @@ fun SendStaticLocation(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
@@ -78,6 +84,8 @@ fun SendStaticLocation(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
@@ -87,6 +95,11 @@ fun SendStaticLocation(
replyMarkup = replyMarkup
)
/**
* @param livePeriod According to Telegram Bots API, must be `0` when sending as an ephemeral message (with
* [receiverUserId] set), as ephemeral messages do not support live location updates. Prefer [SendStaticLocation]
* for ephemeral locations.
*/
fun SendLiveLocation(
chatId: ChatIdentifier,
latitude: Double,
@@ -98,6 +111,8 @@ fun SendLiveLocation(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
@@ -116,6 +131,8 @@ fun SendLiveLocation(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
@@ -132,9 +149,15 @@ sealed interface SendLocation<T : LocationContent> : SendContentMessageRequest<C
HorizontallyAccured,
Livable,
ProximityAlertable,
Headed {
Headed,
OptionallyEphemeralSendRequest {
override fun method(): String = "sendLocation"
/**
* @property livePeriod According to Telegram Bots API, must be `0` when sending as an ephemeral message (with
* [receiverUserId] set), as ephemeral messages do not support live location updates. Prefer [Static]
* for ephemeral locations.
*/
@Serializable
data class Live (
@SerialName(chatIdField)
@@ -165,6 +188,10 @@ sealed interface SendLocation<T : LocationContent> : SendContentMessageRequest<C
@OptIn(ExperimentalSerializationApi::class)
@EncodeDefault
override val businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
@SerialName(receiverUserIdField)
override val receiverUserId: UserId? = null,
@SerialName(callbackQueryIdField)
override val callbackQueryId: CallbackQueryId? = null,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(protectContentField)
@@ -215,6 +242,10 @@ sealed interface SendLocation<T : LocationContent> : SendContentMessageRequest<C
@OptIn(ExperimentalSerializationApi::class)
@EncodeDefault
override val businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
@SerialName(receiverUserIdField)
override val receiverUserId: UserId? = null,
@SerialName(callbackQueryIdField)
override val callbackQueryId: CallbackQueryId? = null,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(protectContentField)
@@ -267,6 +298,10 @@ sealed interface SendLocation<T : LocationContent> : SendContentMessageRequest<C
val directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
@SerialName(businessConnectionIdField)
val businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
@SerialName(receiverUserIdField)
val receiverUserId: UserId? = null,
@SerialName(callbackQueryIdField)
val callbackQueryId: CallbackQueryId? = null,
@SerialName(disableNotificationField)
val disableNotification: Boolean = false,
@SerialName(protectContentField)
@@ -297,6 +332,8 @@ sealed interface SendLocation<T : LocationContent> : SendContentMessageRequest<C
threadId = surrogate.threadId,
directMessageThreadId = surrogate.directMessageThreadId,
businessConnectionId = surrogate.businessConnectionId,
receiverUserId = surrogate.receiverUserId,
callbackQueryId = surrogate.callbackQueryId,
disableNotification = surrogate.disableNotification,
protectContent = surrogate.protectContent,
allowPaidBroadcast = surrogate.allowPaidBroadcast,
@@ -316,6 +353,8 @@ sealed interface SendLocation<T : LocationContent> : SendContentMessageRequest<C
threadId = surrogate.threadId,
directMessageThreadId = surrogate.directMessageThreadId,
businessConnectionId = surrogate.businessConnectionId,
receiverUserId = surrogate.receiverUserId,
callbackQueryId = surrogate.callbackQueryId,
disableNotification = surrogate.disableNotification,
protectContent = surrogate.protectContent,
allowPaidBroadcast = surrogate.allowPaidBroadcast,
@@ -340,6 +379,8 @@ sealed interface SendLocation<T : LocationContent> : SendContentMessageRequest<C
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,

View File

@@ -30,6 +30,8 @@ fun SendTextMessage(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
@@ -45,6 +47,8 @@ fun SendTextMessage(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
linkPreviewOptions = linkPreviewOptions,
disableNotification = disableNotification,
protectContent = protectContent,
@@ -62,6 +66,8 @@ fun SendTextMessage(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
@@ -77,6 +83,8 @@ fun SendTextMessage(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
linkPreviewOptions = linkPreviewOptions,
disableNotification = disableNotification,
protectContent = protectContent,
@@ -108,6 +116,10 @@ data class SendTextMessage internal constructor(
override val directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
@SerialName(businessConnectionIdField)
override val businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
@SerialName(receiverUserIdField)
override val receiverUserId: UserId? = null,
@SerialName(callbackQueryIdField)
override val callbackQueryId: CallbackQueryId? = null,
@SerialName(linkPreviewOptionsField)
override val linkPreviewOptions: LinkPreviewOptions? = null,
@SerialName(disableNotificationField)
@@ -127,7 +139,8 @@ data class SendTextMessage internal constructor(
) : SendContentMessageRequest<ChatContentMessage<TextContent>>,
ReplyingMarkupSendMessageRequest<ChatContentMessage<TextContent>>,
TextableSendMessageRequest<ChatContentMessage<TextContent>>,
LinkPreviewOptionsContainer
LinkPreviewOptionsContainer,
OptionallyEphemeralSendRequest
{
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text)

View File

@@ -45,6 +45,10 @@ data class SendVenue(
override val directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
@SerialName(businessConnectionIdField)
override val businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
@SerialName(receiverUserIdField)
override val receiverUserId: UserId? = null,
@SerialName(callbackQueryIdField)
override val callbackQueryId: CallbackQueryId? = null,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(protectContentField)
@@ -62,7 +66,8 @@ data class SendVenue(
) : SendContentMessageRequest<ChatContentMessage<VenueContent>>,
ReplyingMarkupSendMessageRequest<ChatContentMessage<VenueContent>>,
TitledSendMessageRequest<ChatContentMessage<VenueContent>>,
PositionedSendMessageRequest<ChatContentMessage<VenueContent>>
PositionedSendMessageRequest<ChatContentMessage<VenueContent>>,
OptionallyEphemeralSendRequest
{
constructor(
chatId: ChatIdentifier,
@@ -70,6 +75,8 @@ data class SendVenue(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
@@ -90,6 +97,8 @@ data class SendVenue(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
@@ -111,6 +120,8 @@ fun Venue.toRequest(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
@@ -124,6 +135,8 @@ fun Venue.toRequest(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,

View File

@@ -0,0 +1,13 @@
package dev.inmo.tgbotapi.requests.send.abstracts
import dev.inmo.tgbotapi.types.CallbackQueryId
import dev.inmo.tgbotapi.types.UserId
/**
* Inheritors of this interface may be sent as ephemeral messages (visible only to [receiverUserId] and the bot)
* by passing a non-null [receiverUserId]. Available for groups/supergroups only.
*/
interface OptionallyEphemeralSendRequest {
val receiverUserId: UserId?
val callbackQueryId: CallbackQueryId?
}

View File

@@ -38,6 +38,8 @@ fun SendAnimation(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
@@ -64,6 +66,8 @@ fun SendAnimation(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
@@ -96,6 +100,8 @@ fun SendAnimation(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
@@ -122,6 +128,8 @@ fun SendAnimation(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
@@ -179,6 +187,10 @@ data class SendAnimationData internal constructor(
override val directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
@SerialName(businessConnectionIdField)
override val businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
@SerialName(receiverUserIdField)
override val receiverUserId: UserId? = null,
@SerialName(callbackQueryIdField)
override val callbackQueryId: CallbackQueryId? = null,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(protectContentField)
@@ -201,7 +213,8 @@ data class SendAnimationData internal constructor(
DuratedSendMessageRequest<ChatContentMessage<AnimationContent>>,
SizedSendMessageRequest<ChatContentMessage<AnimationContent>>,
WithCustomizableCaptionRequest<ChatContentMessage<AnimationContent>>,
OptionallyWithSpoilerRequest
OptionallyWithSpoilerRequest,
OptionallyEphemeralSendRequest
{
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text ?: return@lazy null)

View File

@@ -37,6 +37,8 @@ fun SendAudio(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
@@ -61,6 +63,8 @@ fun SendAudio(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
@@ -91,6 +95,8 @@ fun SendAudio(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
@@ -115,6 +121,8 @@ fun SendAudio(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
@@ -168,6 +176,10 @@ data class SendAudioData internal constructor(
override val directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
@SerialName(businessConnectionIdField)
override val businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
@SerialName(receiverUserIdField)
override val receiverUserId: UserId? = null,
@SerialName(callbackQueryIdField)
override val callbackQueryId: CallbackQueryId? = null,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(protectContentField)
@@ -189,7 +201,8 @@ data class SendAudioData internal constructor(
ThumbedSendMessageRequest<ChatContentMessage<AudioContent>>,
TitledSendMessageRequest<ChatContentMessage<AudioContent>>,
DuratedSendMessageRequest<ChatContentMessage<AudioContent>>,
Performerable
Performerable,
OptionallyEphemeralSendRequest
{
override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextSources(text ?: return@lazy null)

View File

@@ -42,6 +42,8 @@ fun SendDocument(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
@@ -64,6 +66,8 @@ fun SendDocument(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
@@ -101,6 +105,8 @@ fun SendDocument(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
@@ -123,6 +129,8 @@ fun SendDocument(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
@@ -180,6 +188,10 @@ data class SendDocumentData internal constructor(
override val directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
@SerialName(businessConnectionIdField)
override val businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
@SerialName(receiverUserIdField)
override val receiverUserId: UserId? = null,
@SerialName(callbackQueryIdField)
override val callbackQueryId: CallbackQueryId? = null,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(protectContentField)
@@ -200,7 +212,8 @@ data class SendDocumentData internal constructor(
SendContentMessageRequest<ChatContentMessage<DocumentContent>>,
ReplyingMarkupSendMessageRequest<ChatContentMessage<DocumentContent>>,
TextableSendMessageRequest<ChatContentMessage<DocumentContent>>,
ThumbedSendMessageRequest<ChatContentMessage<DocumentContent>>
ThumbedSendMessageRequest<ChatContentMessage<DocumentContent>>,
OptionallyEphemeralSendRequest
{
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text ?: return@lazy null)

View File

@@ -35,6 +35,8 @@ fun SendLivePhoto(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
@@ -58,6 +60,8 @@ fun SendLivePhoto(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
@@ -87,6 +91,8 @@ fun SendLivePhoto(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
@@ -110,6 +116,8 @@ fun SendLivePhoto(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
@@ -161,6 +169,10 @@ data class SendLivePhotoData internal constructor(
override val directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
@SerialName(businessConnectionIdField)
override val businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
@SerialName(receiverUserIdField)
override val receiverUserId: UserId? = null,
@SerialName(callbackQueryIdField)
override val callbackQueryId: CallbackQueryId? = null,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(protectContentField)
@@ -180,7 +192,8 @@ data class SendLivePhotoData internal constructor(
ReplyingMarkupSendMessageRequest<ChatContentMessage<LivePhotoContent>>,
TextableSendMessageRequest<ChatContentMessage<LivePhotoContent>>,
WithCustomizableCaptionRequest<ChatContentMessage<LivePhotoContent>>,
OptionallyWithSpoilerRequest
OptionallyWithSpoilerRequest,
OptionallyEphemeralSendRequest
{
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text ?: return@lazy null)

View File

@@ -33,6 +33,8 @@ fun SendPhoto(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
@@ -52,6 +54,8 @@ fun SendPhoto(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
@@ -79,6 +83,8 @@ fun SendPhoto(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
@@ -98,6 +104,8 @@ fun SendPhoto(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
@@ -147,6 +155,10 @@ data class SendPhotoData internal constructor(
override val directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
@SerialName(businessConnectionIdField)
override val businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
@SerialName(receiverUserIdField)
override val receiverUserId: UserId? = null,
@SerialName(callbackQueryIdField)
override val callbackQueryId: CallbackQueryId? = null,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(protectContentField)
@@ -166,7 +178,8 @@ data class SendPhotoData internal constructor(
ReplyingMarkupSendMessageRequest<ChatContentMessage<PhotoContent>>,
TextableSendMessageRequest<ChatContentMessage<PhotoContent>>,
WithCustomizableCaptionRequest<ChatContentMessage<PhotoContent>>,
OptionallyWithSpoilerRequest
OptionallyWithSpoilerRequest,
OptionallyEphemeralSendRequest
{
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text ?: return@lazy null)

View File

@@ -2,6 +2,7 @@ package dev.inmo.tgbotapi.requests.send.media
import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest
import dev.inmo.tgbotapi.requests.send.abstracts.OptionallyEphemeralSendRequest
import dev.inmo.tgbotapi.requests.send.abstracts.ReplyingMarkupSendMessageRequest
import dev.inmo.tgbotapi.requests.send.abstracts.SendContentMessageRequest
import dev.inmo.tgbotapi.requests.send.abstracts.SendMessageRequest
@@ -22,6 +23,8 @@ fun SendSticker(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
emoji: String? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
@@ -36,6 +39,8 @@ fun SendSticker(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
emoji = emoji,
disableNotification = disableNotification,
protectContent = protectContent,
@@ -74,6 +79,10 @@ data class SendStickerByFileId internal constructor(
override val directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
@SerialName(businessConnectionIdField)
override val businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
@SerialName(receiverUserIdField)
override val receiverUserId: UserId? = null,
@SerialName(callbackQueryIdField)
override val callbackQueryId: CallbackQueryId? = null,
@SerialName(emojiField)
val emoji: String? = null,
@SerialName(disableNotificationField)
@@ -90,7 +99,7 @@ data class SendStickerByFileId internal constructor(
override val replyParameters: ReplyParameters? = null,
@SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null
) : SendContentMessageRequest<ChatContentMessage<StickerContent>>, ReplyingMarkupSendMessageRequest<ChatContentMessage<StickerContent>> {
) : SendContentMessageRequest<ChatContentMessage<StickerContent>>, ReplyingMarkupSendMessageRequest<ChatContentMessage<StickerContent>>, OptionallyEphemeralSendRequest {
override fun method(): String = "sendSticker"
override val resultDeserializer: DeserializationStrategy<ChatContentMessage<StickerContent>>
get() = commonResultDeserializer

View File

@@ -43,6 +43,8 @@ fun SendVideo(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
@@ -73,6 +75,8 @@ fun SendVideo(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
@@ -108,6 +112,8 @@ fun SendVideo(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
@@ -138,6 +144,8 @@ fun SendVideo(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
@@ -201,6 +209,10 @@ data class SendVideoData internal constructor(
override val directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
@SerialName(businessConnectionIdField)
override val businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
@SerialName(receiverUserIdField)
override val receiverUserId: UserId? = null,
@SerialName(callbackQueryIdField)
override val callbackQueryId: CallbackQueryId? = null,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(protectContentField)
@@ -226,7 +238,8 @@ data class SendVideoData internal constructor(
CoveredSendMessageRequest<ChatContentMessage<VideoContent>>,
WithCustomStartMediaData,
OptionallyWithSpoilerRequest,
OptionallyStreamable
OptionallyStreamable,
OptionallyEphemeralSendRequest
{
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text ?: return@lazy null)

View File

@@ -25,6 +25,8 @@ fun SendVideoNote(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
@@ -45,6 +47,8 @@ fun SendVideoNote(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
@@ -90,6 +94,10 @@ data class SendVideoNoteData internal constructor(
override val directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
@SerialName(businessConnectionIdField)
override val businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
@SerialName(receiverUserIdField)
override val receiverUserId: UserId? = null,
@SerialName(callbackQueryIdField)
override val callbackQueryId: CallbackQueryId? = null,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(protectContentField)
@@ -109,7 +117,8 @@ data class SendVideoNoteData internal constructor(
ReplyingMarkupSendMessageRequest<ChatContentMessage<VideoNoteContent>>,
ThumbedSendMessageRequest<ChatContentMessage<VideoNoteContent>>,
DuratedSendMessageRequest<ChatContentMessage<VideoNoteContent>>,
SizedSendMessageRequest<ChatContentMessage<VideoNoteContent>>
SizedSendMessageRequest<ChatContentMessage<VideoNoteContent>>,
OptionallyEphemeralSendRequest
{
override val height: Int?
get() = width

View File

@@ -31,6 +31,8 @@ fun SendVoice(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowPaidBroadcast: Boolean = false,
@@ -51,6 +53,8 @@ fun SendVoice(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
@@ -77,6 +81,8 @@ fun SendVoice(
threadId: MessageThreadId? = chatId.threadId,
directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
receiverUserId: UserId? = null,
callbackQueryId: CallbackQueryId? = null,
duration: Long? = null,
disableNotification: Boolean = false,
protectContent: Boolean = false,
@@ -98,6 +104,8 @@ fun SendVoice(
threadId = threadId,
directMessageThreadId = directMessageThreadId,
businessConnectionId = businessConnectionId,
receiverUserId = receiverUserId,
callbackQueryId = callbackQueryId,
disableNotification = disableNotification,
protectContent = protectContent,
allowPaidBroadcast = allowPaidBroadcast,
@@ -145,6 +153,10 @@ data class SendVoiceData internal constructor(
override val directMessageThreadId: DirectMessageThreadId? = chatId.directMessageThreadId,
@SerialName(businessConnectionIdField)
override val businessConnectionId: BusinessConnectionId? = chatId.businessConnectionId,
@SerialName(receiverUserIdField)
override val receiverUserId: UserId? = null,
@SerialName(callbackQueryIdField)
override val callbackQueryId: CallbackQueryId? = null,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(protectContentField)
@@ -163,7 +175,8 @@ data class SendVoiceData internal constructor(
SendContentMessageRequest<ChatContentMessage<VoiceContent>>,
ReplyingMarkupSendMessageRequest<ChatContentMessage<VoiceContent>>,
TextableSendMessageRequest<ChatContentMessage<VoiceContent>>,
DuratedSendMessageRequest<ChatContentMessage<VoiceContent>>
DuratedSendMessageRequest<ChatContentMessage<VoiceContent>>,
OptionallyEphemeralSendRequest
{
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text ?: return@lazy null)

View File

@@ -14,7 +14,9 @@ data class BotCommand(
@SerialName(botCommandField)
val command: String,
@SerialName(descriptionField)
val description: String
val description: String,
@SerialName(isEphemeralField)
val isEphemeral: Boolean = false
) {
init {
if (command.length !in botCommandLengthLimit) {

View File

@@ -466,6 +466,7 @@ const val botCommandField = "command"
const val botCommandFullField = "bot_command"
const val botCommandsField = "commands"
const val scopeField = "scope"
const val isEphemeralField = "is_ephemeral"
const val isMemberField = "is_member"
const val isForumField = "is_forum"
@@ -756,6 +757,9 @@ const val mainFrameTimestampField = "main_frame_timestamp"
const val firstProfileAudioField = "first_profile_audio"
const val paidMessageStarCountField = "paid_message_star_count"
const val senderTagField = "sender_tag"
const val receiverUserField = "receiver_user"
const val receiverUserIdField = "receiver_user_id"
const val ephemeralMessageIdField = "ephemeral_message_id"
const val countField = "count"
const val ratingField = "rating"
const val uniqueGiftColorsField = "unique_gift_colors"

View File

@@ -0,0 +1,16 @@
package dev.inmo.tgbotapi.types
import kotlinx.serialization.Serializable
import kotlin.jvm.JvmInline
@Serializable
@JvmInline
value class EphemeralMessageId(
val long: Long
) {
override fun toString(): String {
return long.toString()
}
}
fun Long.asEphemeralMessageId() = EphemeralMessageId(this)

View File

@@ -1,12 +1,13 @@
package dev.inmo.tgbotapi.types
import dev.inmo.tgbotapi.abstracts.TextedInput
import dev.inmo.tgbotapi.abstracts.WithMessageId
import dev.inmo.tgbotapi.types.checklists.ChecklistTaskId
import dev.inmo.tgbotapi.types.polls.PollOptionPersistentId
import dev.inmo.tgbotapi.types.message.ParseMode
import dev.inmo.tgbotapi.types.message.RawMessageEntity
import dev.inmo.tgbotapi.types.message.abstracts.Message
import dev.inmo.tgbotapi.types.message.abstracts.OptionallyFromUserMessage
import dev.inmo.tgbotapi.types.message.abstracts.PossiblyEphemeralMessage
import dev.inmo.tgbotapi.types.message.asTextSources
import dev.inmo.tgbotapi.types.message.textsources.TextSource
import dev.inmo.tgbotapi.types.message.textsources.TextSourcesList
@@ -19,9 +20,9 @@ import kotlinx.serialization.Serializable
@Serializable
data class ReplyParameters internal constructor(
@SerialName(chatIdField)
val chatIdentifier: ChatIdentifier,
val chatIdentifier: ChatIdentifier?,
@SerialName(messageIdField)
override val messageId: MessageId,
val messageId: MessageId?,
@SerialName(allowSendingWithoutReplyField)
val allowSendingWithoutReply: Boolean? = null,
@SerialName(quoteField)
@@ -36,13 +37,36 @@ data class ReplyParameters internal constructor(
val checklistTaskId: ChecklistTaskId? = null,
@SerialName(pollOptionIdField)
val pollOptionId: PollOptionPersistentId? = null,
) : WithMessageId, TextedInput {
@SerialName(ephemeralMessageIdField)
val ephemeralMessageId: EphemeralMessageId? = null,
) : TextedInput {
init {
require(messageId != null || ephemeralMessageId != null) {
"Either messageId or ephemeralMessageId must be specified for ReplyParameters"
}
}
override val text: String?
get() = quote
override val textSources: List<TextSource> by lazy {
quoteEntities ?.asTextSources(quote ?: return@lazy emptyList()) ?: emptyList()
}
/**
* Builds [ReplyParameters] targeting an ephemeral message by its [ephemeralMessageId]. The reply itself must
* also be sent as ephemeral (see `receiverUserId` of the corresponding send request); [chatIdentifier] and
* [quote]-related fields are not supported for such replies.
*/
constructor(
ephemeralMessageId: EphemeralMessageId,
allowSendingWithoutReply: Boolean? = null,
) : this(
chatIdentifier = null,
messageId = null,
allowSendingWithoutReply = allowSendingWithoutReply,
ephemeralMessageId = ephemeralMessageId
)
constructor(
chatIdentifier: ChatIdentifier,
messageId: MessageId,
@@ -194,3 +218,23 @@ data class ReplyParameters internal constructor(
pollOptionId
)
}
/**
* Builds [ReplyParameters] targeting [this] ephemeral message (via its [PossiblyEphemeralMessage.ephemeralMessageId]),
* or `null` if [this] is not an ephemeral message. Used by `reply(to = ...)` helpers to automatically address a
* reply through `ephemeral_message_id` when the target message is itself ephemeral.
*/
fun Message.ephemeralReplyParametersOrNull(allowSendingWithoutReply: Boolean? = null): ReplyParameters? =
(this as? PossiblyEphemeralMessage) ?.ephemeralMessageId ?.let {
ReplyParameters(it, allowSendingWithoutReply)
}
/**
* The [UserId] that should receive an ephemeral reply to [this] message (`null` if [this] is not ephemeral):
* the original ephemeral message's [PossiblyEphemeralMessage.receiverUser], falling back to the message sender
* ([OptionallyFromUserMessage.from]) when [PossiblyEphemeralMessage.receiverUser] is missing.
*/
val Message.ephemeralReplyReceiverUserIdOrNull: UserId?
get() = (this as? PossiblyEphemeralMessage) ?.takeIf { it.ephemeralMessageId != null } ?.let {
it.receiverUser ?.id ?: (this as? OptionallyFromUserMessage) ?.from ?.id
}

View File

@@ -189,6 +189,11 @@ data class CommonGroupContentMessageImpl<T : MessageContent>(
override val cost: Int? = null,
@SerialName(senderTagField)
override val senderTag: UserTag? = null,
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
@SerialName(receiverUserField)
override val receiverUser: PreviewUser? = null,
@SerialName(ephemeralMessageIdField)
override val ephemeralMessageId: EphemeralMessageId? = null,
) : CommonGroupContentMessage<T> {
constructor(
chat: PreviewGroupChat,
@@ -475,6 +480,11 @@ data class CommonForumContentMessageImpl<T : MessageContent>(
override val cost: Int? = null,
@SerialName(senderTagField)
override val senderTag: UserTag? = null,
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
@SerialName(receiverUserField)
override val receiverUser: PreviewUser? = null,
@SerialName(ephemeralMessageIdField)
override val ephemeralMessageId: EphemeralMessageId? = null,
) : CommonForumContentMessage<T> {
constructor(
chat: PreviewForumChat,
@@ -537,7 +547,12 @@ data class CommonChannelDirectMessagesContentMessageImpl<T : MessageContent>(
@SerialName(paidMessageStarCountField)
override val cost: Int? = null,
@SerialName(senderTagField)
override val senderTag: UserTag? = null
override val senderTag: UserTag? = null,
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
@SerialName(receiverUserField)
override val receiverUser: PreviewUser? = null,
@SerialName(ephemeralMessageIdField)
override val ephemeralMessageId: EphemeralMessageId? = null,
) : CommonChannelDirectMessagesContentMessage<T> {
constructor(
chat: PreviewChannelDirectMessagesChat,
@@ -597,7 +612,12 @@ data class CommonSuggestedChannelDirectMessagesContentMessageImpl<T : MessageCon
@SerialName(paidMessageStarCountField)
override val cost: Int? = null,
@SerialName(senderTagField)
override val senderTag: UserTag? = null
override val senderTag: UserTag? = null,
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
@SerialName(receiverUserField)
override val receiverUser: PreviewUser? = null,
@SerialName(ephemeralMessageIdField)
override val ephemeralMessageId: EphemeralMessageId? = null,
) : CommonSuggestedChannelDirectMessagesContentMessage<T> {
constructor(
chat: PreviewChannelDirectMessagesChat,

View File

@@ -72,6 +72,9 @@ internal data class RawMessage(
private val from: PreviewUser? = null,
private val sender_tag: UserTag? = null,
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
private val receiver_user: PreviewUser? = null,
private val ephemeral_message_id: EphemeralMessageId? = null,
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
private val sender_chat: PreviewPublicChat? = null,
private val forward_origin: MessageOrigin? = null,
private val is_topic_message: Boolean? = null,
@@ -534,6 +537,8 @@ internal data class RawMessage(
fromOffline = is_from_offline,
cost = paid_star_count,
senderTag = sender_tag,
receiverUser = receiver_user,
ephemeralMessageId = ephemeral_message_id,
)
}
}
@@ -578,6 +583,8 @@ internal data class RawMessage(
suggestedPostInfo = suggested_post_info,
cost = paid_star_count,
senderTag = sender_tag,
receiverUser = receiver_user,
ephemeralMessageId = ephemeral_message_id,
)
}
}
@@ -687,6 +694,8 @@ internal data class RawMessage(
fromOffline = is_from_offline,
cost = paid_star_count,
senderTag = sender_tag,
receiverUser = receiver_user,
ephemeralMessageId = ephemeral_message_id,
)
}
} else {
@@ -762,7 +771,9 @@ internal data class RawMessage(
senderBoostsCount = sender_boost_count,
fromOffline = is_from_offline,
cost = paid_star_count,
senderTag = sender_tag
senderTag = sender_tag,
receiverUser = receiver_user,
ephemeralMessageId = ephemeral_message_id,
)
}
}
@@ -841,6 +852,8 @@ internal data class RawMessage(
fromOffline = is_from_offline,
cost = paid_star_count,
senderTag = sender_tag,
receiverUser = receiver_user,
ephemeralMessageId = ephemeral_message_id,
)
}
}

View File

@@ -12,7 +12,7 @@ sealed interface GroupContentMessage<T : MessageContent> : PublicContentMessage<
override val chat: PreviewGroupChat
}
sealed interface PotentiallyFromUserGroupContentMessage<T : MessageContent> : GroupContentMessage<T> {
sealed interface PotentiallyFromUserGroupContentMessage<T : MessageContent> : GroupContentMessage<T>, PossiblyEphemeralMessage {
val senderBoostsCount: Int?
val senderTag: UserTag?
}

View File

@@ -0,0 +1,9 @@
package dev.inmo.tgbotapi.types.message.abstracts
import dev.inmo.tgbotapi.types.EphemeralMessageId
import dev.inmo.tgbotapi.types.chat.PreviewUser
interface PossiblyEphemeralMessage : Message {
val receiverUser: PreviewUser?
val ephemeralMessageId: EphemeralMessageId?
}