1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2026-08-18 07:06:25 +00:00

improve replies with ephemeral

This commit is contained in:
2026-08-15 00:15:12 +06:00
parent 8b0e0bf820
commit 6fbe2e5649
7 changed files with 3315 additions and 166 deletions

View File

@@ -15316,7 +15316,9 @@ public final class dev/inmo/tgbotapi/types/ReplyInfo$ToStory$Companion {
public abstract interface class dev/inmo/tgbotapi/types/ReplyParameters {
public static final field Companion Ldev/inmo/tgbotapi/types/ReplyParameters$Companion;
public abstract fun getAllowSendingWithoutReply ()Ljava/lang/Boolean;
public abstract fun getChecklistTaskId-Wby8Lsc ()Ldev/inmo/tgbotapi/types/checklists/ChecklistTaskId;
public abstract fun getMessageId-CigXjpw ()Ldev/inmo/tgbotapi/types/MessageId;
public abstract fun getPollOptionId-y3a_nt8 ()Ljava/lang/String;
}
public final class dev/inmo/tgbotapi/types/ReplyParameters$Chat : dev/inmo/tgbotapi/abstracts/TextedInput, dev/inmo/tgbotapi/abstracts/WithMessageId, dev/inmo/tgbotapi/types/ReplyParameters {
@@ -15333,10 +15335,10 @@ public final class dev/inmo/tgbotapi/types/ReplyParameters$Chat : dev/inmo/tgbot
public fun equals (Ljava/lang/Object;)Z
public fun getAllowSendingWithoutReply ()Ljava/lang/Boolean;
public final fun getChatIdentifier ()Ldev/inmo/tgbotapi/types/ChatIdentifier;
public final fun getChecklistTaskId-Wby8Lsc ()Ldev/inmo/tgbotapi/types/checklists/ChecklistTaskId;
public fun getChecklistTaskId-Wby8Lsc ()Ldev/inmo/tgbotapi/types/checklists/ChecklistTaskId;
public fun getMessageId-APLFQys ()J
public synthetic fun getMessageId-CigXjpw ()Ldev/inmo/tgbotapi/types/MessageId;
public final fun getPollOptionId-y3a_nt8 ()Ljava/lang/String;
public fun getPollOptionId-y3a_nt8 ()Ljava/lang/String;
public final fun getQuote ()Ljava/lang/String;
public final fun getQuoteParseMode ()Ldev/inmo/tgbotapi/types/message/ParseMode;
public final fun getQuotePosition ()Ljava/lang/Integer;
@@ -15359,6 +15361,8 @@ public final class dev/inmo/tgbotapi/types/ReplyParameters$Companion {
public static synthetic fun invoke-HmWr8k0$default (Ldev/inmo/tgbotapi/types/ReplyParameters$Companion;Ldev/inmo/tgbotapi/types/ChatIdentifier;JLjava/lang/Boolean;Ljava/lang/Integer;Ldev/inmo/tgbotapi/types/checklists/ChecklistTaskId;Ljava/lang/String;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/ReplyParameters$Chat;
public final fun invoke-SSz3Fa8 (Lkotlin/Triple;Ljava/lang/String;Ldev/inmo/tgbotapi/types/message/ParseMode;Ljava/lang/Boolean;Ljava/lang/Integer;Ldev/inmo/tgbotapi/types/checklists/ChecklistTaskId;Ljava/lang/String;)Ldev/inmo/tgbotapi/types/ReplyParameters$Chat;
public static synthetic fun invoke-SSz3Fa8$default (Ldev/inmo/tgbotapi/types/ReplyParameters$Companion;Lkotlin/Triple;Ljava/lang/String;Ldev/inmo/tgbotapi/types/message/ParseMode;Ljava/lang/Boolean;Ljava/lang/Integer;Ldev/inmo/tgbotapi/types/checklists/ChecklistTaskId;Ljava/lang/String;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/ReplyParameters$Chat;
public final fun invoke-Y3Yf5gs (JLjava/lang/Boolean;Ldev/inmo/tgbotapi/types/checklists/ChecklistTaskId;Ljava/lang/String;)Ldev/inmo/tgbotapi/types/ReplyParameters$Ephemeral;
public static synthetic fun invoke-Y3Yf5gs$default (Ldev/inmo/tgbotapi/types/ReplyParameters$Companion;JLjava/lang/Boolean;Ldev/inmo/tgbotapi/types/checklists/ChecklistTaskId;Ljava/lang/String;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/ReplyParameters$Ephemeral;
public final fun invoke-YCjLccs (Ldev/inmo/tgbotapi/types/ChatIdentifier;JLjava/lang/String;Ldev/inmo/tgbotapi/types/message/ParseMode;Ljava/lang/Boolean;Ljava/lang/Integer;Ldev/inmo/tgbotapi/types/checklists/ChecklistTaskId;Ljava/lang/String;)Ldev/inmo/tgbotapi/types/ReplyParameters$Chat;
public static synthetic fun invoke-YCjLccs$default (Ldev/inmo/tgbotapi/types/ReplyParameters$Companion;Ldev/inmo/tgbotapi/types/ChatIdentifier;JLjava/lang/String;Ldev/inmo/tgbotapi/types/message/ParseMode;Ljava/lang/Boolean;Ljava/lang/Integer;Ldev/inmo/tgbotapi/types/checklists/ChecklistTaskId;Ljava/lang/String;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/ReplyParameters$Chat;
public final fun invoke-Z5nmqEk (Ldev/inmo/tgbotapi/types/message/abstracts/Message;Ljava/lang/String;Ldev/inmo/tgbotapi/types/message/ParseMode;Ljava/lang/Boolean;Ljava/lang/Integer;Ldev/inmo/tgbotapi/types/checklists/ChecklistTaskId;Ljava/lang/String;)Ldev/inmo/tgbotapi/types/ReplyParameters$Chat;
@@ -15374,16 +15378,20 @@ public final class dev/inmo/tgbotapi/types/ReplyParameters$Companion {
public final class dev/inmo/tgbotapi/types/ReplyParameters$Ephemeral : dev/inmo/tgbotapi/types/ReplyParameters {
public static final field Companion Ldev/inmo/tgbotapi/types/ReplyParameters$Ephemeral$Companion;
public synthetic fun <init> (JLjava/lang/Boolean;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (JLjava/lang/Boolean;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (JLjava/lang/Boolean;Ldev/inmo/tgbotapi/types/checklists/ChecklistTaskId;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (JLjava/lang/Boolean;Ldev/inmo/tgbotapi/types/checklists/ChecklistTaskId;Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1-TazDcj0 ()J
public final fun component2 ()Ljava/lang/Boolean;
public final fun copy-DIpU5II (JLjava/lang/Boolean;)Ldev/inmo/tgbotapi/types/ReplyParameters$Ephemeral;
public static synthetic fun copy-DIpU5II$default (Ldev/inmo/tgbotapi/types/ReplyParameters$Ephemeral;JLjava/lang/Boolean;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/ReplyParameters$Ephemeral;
public final fun component3-Wby8Lsc ()Ldev/inmo/tgbotapi/types/checklists/ChecklistTaskId;
public final fun component4-y3a_nt8 ()Ljava/lang/String;
public final fun copy-Y3Yf5gs (JLjava/lang/Boolean;Ldev/inmo/tgbotapi/types/checklists/ChecklistTaskId;Ljava/lang/String;)Ldev/inmo/tgbotapi/types/ReplyParameters$Ephemeral;
public static synthetic fun copy-Y3Yf5gs$default (Ldev/inmo/tgbotapi/types/ReplyParameters$Ephemeral;JLjava/lang/Boolean;Ldev/inmo/tgbotapi/types/checklists/ChecklistTaskId;Ljava/lang/String;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/ReplyParameters$Ephemeral;
public fun equals (Ljava/lang/Object;)Z
public fun getAllowSendingWithoutReply ()Ljava/lang/Boolean;
public fun getChecklistTaskId-Wby8Lsc ()Ldev/inmo/tgbotapi/types/checklists/ChecklistTaskId;
public final fun getEphemeralMessageId-TazDcj0 ()J
public fun getMessageId-CigXjpw ()Ldev/inmo/tgbotapi/types/MessageId;
public fun getPollOptionId-y3a_nt8 ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@@ -15402,8 +15410,8 @@ public final class dev/inmo/tgbotapi/types/ReplyParameters$Serializer : kotlinx/
}
public final class dev/inmo/tgbotapi/types/ReplyParametersKt {
public static final fun ephemeralReplyParametersOrNull (Ldev/inmo/tgbotapi/types/message/abstracts/Message;Ljava/lang/Boolean;)Ldev/inmo/tgbotapi/types/ReplyParameters;
public static synthetic fun ephemeralReplyParametersOrNull$default (Ldev/inmo/tgbotapi/types/message/abstracts/Message;Ljava/lang/Boolean;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/ReplyParameters;
public static final fun ephemeralReplyParametersOrNull-4LbmTBs (Ldev/inmo/tgbotapi/types/message/abstracts/Message;Ljava/lang/Boolean;Ldev/inmo/tgbotapi/types/EphemeralMessageId;Ldev/inmo/tgbotapi/types/checklists/ChecklistTaskId;Ljava/lang/String;)Ldev/inmo/tgbotapi/types/ReplyParameters;
public static synthetic fun ephemeralReplyParametersOrNull-4LbmTBs$default (Ldev/inmo/tgbotapi/types/message/abstracts/Message;Ljava/lang/Boolean;Ldev/inmo/tgbotapi/types/EphemeralMessageId;Ldev/inmo/tgbotapi/types/checklists/ChecklistTaskId;Ljava/lang/String;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/ReplyParameters;
public static final fun getEphemeralReplyReceiverUserIdOrNull (Ldev/inmo/tgbotapi/types/message/abstracts/Message;)Ldev/inmo/tgbotapi/types/IdChatIdentifier;
}

View File

@@ -26,6 +26,8 @@ import kotlinx.serialization.encoding.Encoder
sealed interface ReplyParameters {
val messageId: MessageId?
val allowSendingWithoutReply: Boolean?
val checklistTaskId: ChecklistTaskId?
val pollOptionId: PollOptionPersistentId?
/**
* Reply parameters targeting a regular message identified by [messageId]. A `null` [chatIdentifier] targets a
@@ -43,8 +45,8 @@ sealed interface ReplyParameters {
val quoteParseMode: ParseMode? = null,
internal val quoteEntities: List<RawMessageEntity>? = null,
val quotePosition: Int? = null,
val checklistTaskId: ChecklistTaskId? = null,
val pollOptionId: PollOptionPersistentId? = null,
override val checklistTaskId: ChecklistTaskId? = null,
override val pollOptionId: PollOptionPersistentId? = null,
) : WithMessageId, ReplyParameters, TextedInput {
override val text: String?
get() = quote
@@ -57,16 +59,31 @@ sealed interface ReplyParameters {
@Serializable(ReplyParameters.Serializer::class)
/**
* Reply parameters targeting an incoming ephemeral message identified by [ephemeralMessageId]. The outgoing
* reply must also be ephemeral; chat and quote fields are unsupported for ephemeral replies.
* reply must also be ephemeral; chat and quote fields are unsupported for ephemeral replies. Type-neutral
* construction is available through the `ReplyParameters(...)` companion factory.
*/
data class Ephemeral(
val ephemeralMessageId: EphemeralMessageId,
override val allowSendingWithoutReply: Boolean? = null,
override val checklistTaskId: ChecklistTaskId? = null,
override val pollOptionId: PollOptionPersistentId? = null,
) : ReplyParameters {
override val messageId: MessageId? = null
}
companion object {
operator fun invoke(
ephemeralMessageId: EphemeralMessageId,
allowSendingWithoutReply: Boolean? = null,
checklistTaskId: ChecklistTaskId? = null,
pollOptionId: PollOptionPersistentId? = null,
): Ephemeral = Ephemeral(
ephemeralMessageId,
allowSendingWithoutReply,
checklistTaskId,
pollOptionId
)
operator fun invoke(
chatIdentifier: ChatIdentifier,
messageId: MessageId,
@@ -250,11 +267,22 @@ sealed interface ReplyParameters {
throw SerializationException("ReplyParameters must contain either message_id or ephemeral_message_id, not both")
}
return when {
surrogate.ephemeralMessageId != null -> Ephemeral(surrogate.ephemeralMessageId, surrogate.allowSendingWithoutReply)
surrogate.ephemeralMessageId != null -> Ephemeral(
ephemeralMessageId = surrogate.ephemeralMessageId,
allowSendingWithoutReply = surrogate.allowSendingWithoutReply,
checklistTaskId = surrogate.checklistTaskId,
pollOptionId = surrogate.pollOptionId
)
surrogate.messageId != null -> Chat(
surrogate.chatIdentifier, surrogate.messageId, surrogate.allowSendingWithoutReply, surrogate.quote,
surrogate.quoteParseMode, surrogate.quoteEntities, surrogate.quotePosition, surrogate.checklistTaskId,
surrogate.pollOptionId
chatIdentifier = surrogate.chatIdentifier,
messageId = surrogate.messageId,
allowSendingWithoutReply = surrogate.allowSendingWithoutReply,
quote = surrogate.quote,
quoteParseMode = surrogate.quoteParseMode,
quoteEntities = surrogate.quoteEntities,
quotePosition = surrogate.quotePosition,
checklistTaskId = surrogate.checklistTaskId,
pollOptionId = surrogate.pollOptionId
)
else -> throw SerializationException("ReplyParameters must contain message_id or ephemeral_message_id")
}
@@ -262,8 +290,23 @@ sealed interface ReplyParameters {
override fun serialize(encoder: Encoder, value: ReplyParameters) {
val surrogate = when (value) {
is Chat -> Surrogate(value.chatIdentifier, value.messageId, value.allowSendingWithoutReply, value.quote, value.quoteParseMode, value.quoteEntities, value.quotePosition, value.checklistTaskId, value.pollOptionId)
is Ephemeral -> Surrogate(allowSendingWithoutReply = value.allowSendingWithoutReply, ephemeralMessageId = value.ephemeralMessageId)
is Chat -> Surrogate(
chatIdentifier = value.chatIdentifier,
messageId = value.messageId,
allowSendingWithoutReply = value.allowSendingWithoutReply,
quote = value.quote,
quoteParseMode = value.quoteParseMode,
quoteEntities = value.quoteEntities,
quotePosition = value.quotePosition,
checklistTaskId = value.checklistTaskId,
pollOptionId = value.pollOptionId
)
is Ephemeral -> Surrogate(
allowSendingWithoutReply = value.allowSendingWithoutReply,
ephemeralMessageId = value.ephemeralMessageId,
checklistTaskId = value.checklistTaskId,
pollOptionId = value.pollOptionId
)
}
encoder.encodeSerializableValue(Surrogate.serializer(), surrogate)
}
@@ -271,12 +314,23 @@ sealed interface ReplyParameters {
}
/**
* Builds [ReplyParameters] targeting the receiver's ephemeral message through
* [PossiblyEphemeralMessage.ephemeralMessageId], or returns `null` for a non-ephemeral receiver.
* Builds [ReplyParameters.Ephemeral] with [allowSendingWithoutReply], [checklistTaskId], and [pollOptionId], targeting
* [ephemeralMessageId]. The target defaults to [PossiblyEphemeralMessage.ephemeralMessageId]; a missing target produces
* `null`.
*/
fun Message.ephemeralReplyParametersOrNull(allowSendingWithoutReply: Boolean? = null): ReplyParameters? =
(this as? PossiblyEphemeralMessage) ?.ephemeralMessageId ?.let {
ReplyParameters.Ephemeral(it, allowSendingWithoutReply)
fun Message.ephemeralReplyParametersOrNull(
allowSendingWithoutReply: Boolean? = null,
ephemeralMessageId: EphemeralMessageId? = (this as? PossiblyEphemeralMessage) ?.ephemeralMessageId,
checklistTaskId: ChecklistTaskId? = null,
pollOptionId: PollOptionPersistentId? = null,
): ReplyParameters? =
ephemeralMessageId ?.let {
ReplyParameters(
ephemeralMessageId = it,
allowSendingWithoutReply = allowSendingWithoutReply,
checklistTaskId = checklistTaskId,
pollOptionId = pollOptionId,
)
}
/**

View File

@@ -1,5 +1,7 @@
package dev.inmo.tgbotapi.types
import dev.inmo.tgbotapi.types.checklists.ChecklistTaskId
import dev.inmo.tgbotapi.types.polls.PollOptionPersistentId
import kotlinx.serialization.SerializationException
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
@@ -33,12 +35,19 @@ class ReplyParametersSerializationTest {
@Test
fun ephemeralRoundTripUsesFlatShape() {
val value: ReplyParameters = ReplyParameters.Ephemeral(EphemeralMessageId(789L), true)
val value: ReplyParameters = ReplyParameters(
ephemeralMessageId = EphemeralMessageId(789L),
allowSendingWithoutReply = true,
checklistTaskId = ChecklistTaskId(12u),
pollOptionId = PollOptionPersistentId("option-id")
)
val encoded = json.encodeToString(value)
val encodedObject = json.parseToJsonElement(encoded).jsonObject
assertTrue("ephemeral_message_id" in encodedObject)
assertTrue("checklist_task_id" in encodedObject)
assertTrue("poll_option_id" in encodedObject)
assertFalse("chat_id" in encodedObject)
assertFalse("message_id" in encodedObject)
assertEquals(value, json.decodeFromString<ReplyParameters>(encoded))