From a0e748f9a9120dbb0db52c49a2cd7aa8bc2a1554 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Mon, 6 Apr 2026 16:11:46 +0600 Subject: [PATCH] add support of PreparedKeyboardButton and savePreparedKeyboardButton --- tgbotapi.api/api/tgbotapi.api.api | 5 ++ .../api/SavePreparedKeyboardButton.kt | 21 +++++ tgbotapi.core/api/tgbotapi.core.api | 90 +++++++++++++++++++ .../requests/SavePreparedKeyboardButton.kt | 40 +++++++++ .../kotlin/dev/inmo/tgbotapi/types/Common.kt | 11 +++ .../types/buttons/PreparedKeyboardButton.kt | 11 +++ .../types/buttons/PreparedKeyboardId.kt | 10 +++ 7 files changed, 188 insertions(+) create mode 100644 tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/SavePreparedKeyboardButton.kt create mode 100644 tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/SavePreparedKeyboardButton.kt create mode 100644 tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/buttons/PreparedKeyboardButton.kt create mode 100644 tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/buttons/PreparedKeyboardId.kt diff --git a/tgbotapi.api/api/tgbotapi.api.api b/tgbotapi.api/api/tgbotapi.api.api index 95245964ef..7b0d2becd3 100644 --- a/tgbotapi.api/api/tgbotapi.api.api +++ b/tgbotapi.api/api/tgbotapi.api.api @@ -189,6 +189,11 @@ public final class dev/inmo/tgbotapi/extensions/api/LogOutKt { public static final fun logOut (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } +public final class dev/inmo/tgbotapi/extensions/api/SavePreparedKeyboardButtonKt { + public static final fun savePreparedKeyboardButton (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Ldev/inmo/tgbotapi/types/chat/User;Ldev/inmo/tgbotapi/types/buttons/KeyboardButton;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun savePreparedKeyboardButton-nc95W0g (Ldev/inmo/tgbotapi/bot/RequestsExecutor;JLdev/inmo/tgbotapi/types/buttons/KeyboardButton;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +} + public final class dev/inmo/tgbotapi/extensions/api/StopPollKt { public static final fun stopPoll-qvzigsQ (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Ldev/inmo/tgbotapi/types/IdChatIdentifier;Ldev/inmo/tgbotapi/types/message/abstracts/AccessibleMessage;Ljava/lang/String;Ldev/inmo/tgbotapi/types/buttons/InlineKeyboardMarkup;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun stopPoll-qvzigsQ (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Ldev/inmo/tgbotapi/types/chat/Chat;Ldev/inmo/tgbotapi/types/message/abstracts/AccessibleMessage;Ljava/lang/String;Ldev/inmo/tgbotapi/types/buttons/InlineKeyboardMarkup;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; diff --git a/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/SavePreparedKeyboardButton.kt b/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/SavePreparedKeyboardButton.kt new file mode 100644 index 0000000000..8196204e4f --- /dev/null +++ b/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/SavePreparedKeyboardButton.kt @@ -0,0 +1,21 @@ +package dev.inmo.tgbotapi.extensions.api + +import dev.inmo.tgbotapi.bot.TelegramBot +import dev.inmo.tgbotapi.requests.SavePreparedKeyboardButton +import dev.inmo.tgbotapi.types.ChatId +import dev.inmo.tgbotapi.types.buttons.KeyboardButton +import dev.inmo.tgbotapi.types.buttons.PreparedKeyboardButton +import dev.inmo.tgbotapi.types.chat.User +import dev.inmo.tgbotapi.types.toChatId + +public suspend fun TelegramBot.savePreparedKeyboardButton( + userId: ChatId, + button: KeyboardButton +): PreparedKeyboardButton = execute( + SavePreparedKeyboardButton(userId = userId, button = button) +) + +public suspend fun TelegramBot.savePreparedKeyboardButton( + user: User, + button: KeyboardButton +): PreparedKeyboardButton = savePreparedKeyboardButton(userId = user.id.toChatId(), button = button) diff --git a/tgbotapi.core/api/tgbotapi.core.api b/tgbotapi.core/api/tgbotapi.core.api index 4c852f3bfb..9e557f47ac 100644 --- a/tgbotapi.core/api/tgbotapi.core.api +++ b/tgbotapi.core/api/tgbotapi.core.api @@ -973,6 +973,38 @@ public final class dev/inmo/tgbotapi/requests/GetUpdatesRequest$DefaultImpls { public static fun method (Ldev/inmo/tgbotapi/requests/GetUpdatesRequest;)Ljava/lang/String; } +public final class dev/inmo/tgbotapi/requests/SavePreparedKeyboardButton : dev/inmo/tgbotapi/requests/abstracts/SimpleRequest { + public static final field Companion Ldev/inmo/tgbotapi/requests/SavePreparedKeyboardButton$Companion; + public synthetic fun (JLdev/inmo/tgbotapi/types/buttons/KeyboardButton;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1-tHkBKVM ()J + public final fun component2 ()Ldev/inmo/tgbotapi/types/buttons/KeyboardButton; + public final fun copy-zv9neSE (JLdev/inmo/tgbotapi/types/buttons/KeyboardButton;)Ldev/inmo/tgbotapi/requests/SavePreparedKeyboardButton; + public static synthetic fun copy-zv9neSE$default (Ldev/inmo/tgbotapi/requests/SavePreparedKeyboardButton;JLdev/inmo/tgbotapi/types/buttons/KeyboardButton;ILjava/lang/Object;)Ldev/inmo/tgbotapi/requests/SavePreparedKeyboardButton; + public fun equals (Ljava/lang/Object;)Z + public final fun getButton ()Ldev/inmo/tgbotapi/types/buttons/KeyboardButton; + public fun getRequestSerializer ()Lkotlinx/serialization/SerializationStrategy; + public fun getResultDeserializer ()Lkotlinx/serialization/DeserializationStrategy; + public final fun getUserId-tHkBKVM ()J + public fun hashCode ()I + public fun method ()Ljava/lang/String; + public fun toString ()Ljava/lang/String; +} + +public final synthetic class dev/inmo/tgbotapi/requests/SavePreparedKeyboardButton$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Ldev/inmo/tgbotapi/requests/SavePreparedKeyboardButton$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ldev/inmo/tgbotapi/requests/SavePreparedKeyboardButton; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Ldev/inmo/tgbotapi/requests/SavePreparedKeyboardButton;)V + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class dev/inmo/tgbotapi/requests/SavePreparedKeyboardButton$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public final class dev/inmo/tgbotapi/requests/SetPassportDataErrors : dev/inmo/tgbotapi/requests/abstracts/SimpleRequest { public static final field Companion Ldev/inmo/tgbotapi/requests/SetPassportDataErrors$Companion; public fun (Ldev/inmo/tgbotapi/types/IdChatIdentifier;Ljava/util/List;)V @@ -11111,6 +11143,7 @@ public final class dev/inmo/tgbotapi/types/CommonKt { public static final field yearField Ljava/lang/String; public static final fun getAllowedConnectionsLength ()Lkotlin/ranges/IntRange; public static final fun getAllowedConnectionsWithLocalServerLength ()Lkotlin/ranges/IntRange; + public static final fun getAllowedToSavePreparedKeyboardButtons ()Ljava/util/Set; public static final fun getBasketballAndFootballDiceResultLimit ()Lkotlin/ranges/IntRange; public static final fun getBotCommandDescriptionLimit ()Lkotlin/ranges/IntRange; public static final fun getBotCommandLengthLimit ()Lkotlin/ranges/IntRange; @@ -16509,6 +16542,63 @@ public final class dev/inmo/tgbotapi/types/buttons/KeyboardMarkupSerializer : ko public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V } +public final class dev/inmo/tgbotapi/types/buttons/PreparedKeyboardButton { + public static final field Companion Ldev/inmo/tgbotapi/types/buttons/PreparedKeyboardButton$Companion; + public synthetic fun (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1-WMoZTbI ()Ljava/lang/String; + public final fun copy-zz-h5ko (Ljava/lang/String;)Ldev/inmo/tgbotapi/types/buttons/PreparedKeyboardButton; + public static synthetic fun copy-zz-h5ko$default (Ldev/inmo/tgbotapi/types/buttons/PreparedKeyboardButton;Ljava/lang/String;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/buttons/PreparedKeyboardButton; + public fun equals (Ljava/lang/Object;)Z + public final fun getId-WMoZTbI ()Ljava/lang/String; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final synthetic class dev/inmo/tgbotapi/types/buttons/PreparedKeyboardButton$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Ldev/inmo/tgbotapi/types/buttons/PreparedKeyboardButton$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ldev/inmo/tgbotapi/types/buttons/PreparedKeyboardButton; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Ldev/inmo/tgbotapi/types/buttons/PreparedKeyboardButton;)V + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class dev/inmo/tgbotapi/types/buttons/PreparedKeyboardButton$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class dev/inmo/tgbotapi/types/buttons/PreparedKeyboardId { + public static final field Companion Ldev/inmo/tgbotapi/types/buttons/PreparedKeyboardId$Companion; + public static final synthetic fun box-impl (Ljava/lang/String;)Ldev/inmo/tgbotapi/types/buttons/PreparedKeyboardId; + public static fun constructor-impl (Ljava/lang/String;)Ljava/lang/String; + public fun equals (Ljava/lang/Object;)Z + public static fun equals-impl (Ljava/lang/String;Ljava/lang/Object;)Z + public static final fun equals-impl0 (Ljava/lang/String;Ljava/lang/String;)Z + public final fun getString ()Ljava/lang/String; + public fun hashCode ()I + public static fun hashCode-impl (Ljava/lang/String;)I + public fun toString ()Ljava/lang/String; + public static fun toString-impl (Ljava/lang/String;)Ljava/lang/String; + public final synthetic fun unbox-impl ()Ljava/lang/String; +} + +public final synthetic class dev/inmo/tgbotapi/types/buttons/PreparedKeyboardId$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Ldev/inmo/tgbotapi/types/buttons/PreparedKeyboardId$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public final fun deserialize-KQHJBJs (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/String; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public final fun serialize-JKX4Qt8 (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/String;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class dev/inmo/tgbotapi/types/buttons/PreparedKeyboardId$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public final class dev/inmo/tgbotapi/types/buttons/QuizKeyboardButtonPollType : dev/inmo/tgbotapi/types/buttons/KeyboardButtonPollType { public static final field INSTANCE Ldev/inmo/tgbotapi/types/buttons/QuizKeyboardButtonPollType; public fun getType ()Ljava/lang/String; diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/SavePreparedKeyboardButton.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/SavePreparedKeyboardButton.kt new file mode 100644 index 0000000000..9314149955 --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/SavePreparedKeyboardButton.kt @@ -0,0 +1,40 @@ +package dev.inmo.tgbotapi.requests + +import dev.inmo.kslog.common.w +import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest +import dev.inmo.tgbotapi.types.ChatId +import dev.inmo.tgbotapi.types.allowedToSavePreparedKeyboardButtons +import dev.inmo.tgbotapi.types.buttonField +import dev.inmo.tgbotapi.types.buttons.KeyboardButton +import dev.inmo.tgbotapi.types.buttons.PreparedKeyboardButton +import dev.inmo.tgbotapi.types.userIdField +import dev.inmo.tgbotapi.utils.DefaultKTgBotAPIKSLog +import kotlinx.serialization.DeserializationStrategy +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerializationStrategy + +@Serializable +data class SavePreparedKeyboardButton( + @SerialName(userIdField) + val userId: ChatId, + @SerialName(buttonField) + val button: KeyboardButton +) : SimpleRequest { + override val resultDeserializer: DeserializationStrategy + get() = PreparedKeyboardButton.serializer() + override val requestSerializer: SerializationStrategy<*> + get() = serializer() + + override fun method(): String = "savePreparedKeyboardButton" + + init { + if (button::class !in allowedToSavePreparedKeyboardButtons) { + DefaultKTgBotAPIKSLog.w { + "According to https://core.telegram.org/bots/api#savepreparedkeyboardbutton it is disallowed to use " + + "anything except request_users, request_chat, or request_managed_bot, but you passed $button " + + "which is not instance of any allowed buttons type" + } + } + } +} diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/Common.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/Common.kt index 17afa8ccf8..ae92bdd80c 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/Common.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/Common.kt @@ -1,9 +1,14 @@ package dev.inmo.tgbotapi.types +import dev.inmo.tgbotapi.types.buttons.KeyboardButton +import dev.inmo.tgbotapi.types.buttons.RequestChatKeyboardButton +import dev.inmo.tgbotapi.types.buttons.RequestManagedBotKeyboardButton +import dev.inmo.tgbotapi.types.buttons.RequestUserKeyboardButton import dev.inmo.tgbotapi.types.location.LiveLocation import dev.inmo.tgbotapi.utils.BuiltinMimeTypes import kotlinx.serialization.Serializable import kotlin.jvm.JvmInline +import kotlin.reflect.KClass typealias ForwardSignature = String @@ -122,6 +127,12 @@ val cloudStorageValueLimit = 0 .. 4096 val cloudStorageKeyRegex = Regex("[A-Za-z0-9_-]{${cloudStorageKeyLimit.first},${cloudStorageKeyLimit.last}}") val cloudStorageValueRegex = Regex(".{${cloudStorageValueLimit.first},${cloudStorageValueLimit.last}}") +val allowedToSavePreparedKeyboardButtons: Set> = setOf( + RequestUserKeyboardButton::class, + RequestChatKeyboardButton::class, + RequestManagedBotKeyboardButton::class, +) + // Made as lazy for correct work in K/JS val telegramInlineModeGifPermittedMimeTypes by lazy { listOf( diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/buttons/PreparedKeyboardButton.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/buttons/PreparedKeyboardButton.kt new file mode 100644 index 0000000000..6313693989 --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/buttons/PreparedKeyboardButton.kt @@ -0,0 +1,11 @@ +package dev.inmo.tgbotapi.types.buttons + +import dev.inmo.tgbotapi.types.idField +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class PreparedKeyboardButton( + @SerialName(idField) + val id: PreparedKeyboardId +) diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/buttons/PreparedKeyboardId.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/buttons/PreparedKeyboardId.kt new file mode 100644 index 0000000000..b45897b32f --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/buttons/PreparedKeyboardId.kt @@ -0,0 +1,10 @@ +package dev.inmo.tgbotapi.types.buttons + +import kotlinx.serialization.Serializable +import kotlin.jvm.JvmInline + +@Serializable +@JvmInline +value class PreparedKeyboardId( + val string: String +) \ No newline at end of file