diff --git a/CHANGELOG.md b/CHANGELOG.md index 95f1fc0b51..36c621dfe1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,18 @@ * `PollAnswer` type was added * `UpdatesFilter` now support work with `PollAnswerUpdate` * `language` field in PreTextSource now correctly passed from telegram MessageEntities +* `KeyboardButton` now is sealed class + * Fixed problem of incorrect representation of this class (any type of request can be created separately) + * Added new types of `KeyboardButton`: + * `UnknownKeyboardButton` + * `SimpleKeyboardButton` + * `RequestContactKeyboardButton` + * `RequestLocationKeyboardButton` + * `RequestPollKeyboardButton` + * Added new type `KeyboardButtonPollType`: + * `UnknownKeyboardButtonPollType` + * `RegularKeyboardButtonPollType` + * `QuizKeyboardButtonPollType` ## 0.22.0 diff --git a/src/commonMain/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/Common.kt b/src/commonMain/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/Common.kt index 6f6be0af49..8d57258013 100644 --- a/src/commonMain/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/Common.kt +++ b/src/commonMain/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/Common.kt @@ -105,6 +105,10 @@ const val pinnedMessageField = "pinned_message" const val customTitleField = "custom_title" const val optionIdsField = "option_ids" +const val requestContactField = "request_contact" +const val requestLocationField = "request_location" +const val requestPollField = "request_poll" + const val requestWriteAccessField = "request_write_access" diff --git a/src/commonMain/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/buttons/KeyboardButton.kt b/src/commonMain/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/buttons/KeyboardButton.kt index 86bceb79f7..4574ea4f9c 100644 --- a/src/commonMain/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/buttons/KeyboardButton.kt +++ b/src/commonMain/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/buttons/KeyboardButton.kt @@ -1,13 +1,90 @@ package com.github.insanusmokrassar.TelegramBotAPI.types.buttons -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable +import com.github.insanusmokrassar.TelegramBotAPI.types.* +import kotlinx.serialization.* +import kotlinx.serialization.json.* + +@Serializable(KeyboardButtonSerializer::class) +sealed class KeyboardButton { + abstract val text: String +} @Serializable -data class KeyboardButton( - val text: String, - @SerialName("request_contact") - val requestContact: Boolean? = null, - @SerialName("request_location") - val requestLocation: Boolean? = null -) +data class SimpleKeyboardButton( + override val text: String +) : KeyboardButton() + +@Serializable +data class UnknownKeyboardButton internal constructor( + override val text: String, + val raw: String +) : KeyboardButton() + +@Serializable +data class RequestContactKeyboardButton( + override val text: String +) : KeyboardButton() { + @SerialName(requestContactField) + val requestContact: Boolean = true +} + +@Serializable +data class RequestLocationKeyboardButton( + override val text: String +) : KeyboardButton() { + @SerialName(requestLocationField) + val requestLocation: Boolean = true +} + +@Serializable +data class RequestPollKeyboardButton( + override val text: String, + @SerialName(requestPollField) + val requestPoll: KeyboardButtonPollType = RegularKeyboardButtonPollType +) : KeyboardButton() + +@Serializer(KeyboardButton::class) +internal object KeyboardButtonSerializer : KSerializer { + override fun deserialize(decoder: Decoder): KeyboardButton { + val asJson = JsonElementSerializer.deserialize(decoder) + + return when { + asJson is JsonPrimitive -> SimpleKeyboardButton(asJson.content) + asJson is JsonObject && asJson.getPrimitiveOrNull(requestContactField) != null -> RequestContactKeyboardButton( + asJson.getPrimitive(textField).content + ) + asJson is JsonObject && asJson.getPrimitiveOrNull(requestContactField) != null -> RequestContactKeyboardButton( + asJson.getPrimitive(textField).content + ) + asJson is JsonObject && asJson.getPrimitiveOrNull(requestLocationField) != null -> RequestLocationKeyboardButton( + asJson.getPrimitive(textField).content + ) + asJson is JsonObject && asJson.getObjectOrNull(requestPollField) != null -> RequestPollKeyboardButton( + asJson.getPrimitive(textField).content, + Json.nonstrict.fromJson( + KeyboardButtonPollType.serializer(), + asJson.getObject(requestPollField) + ) + ) + else -> UnknownKeyboardButton( + when (asJson) { + is JsonObject -> asJson.getPrimitive(textField).content + is JsonArray -> "" + is JsonPrimitive -> asJson.content + }, + asJson.toString() + ) + } + } + + override fun serialize(encoder: Encoder, obj: KeyboardButton) { + when (obj) { + is RequestContactKeyboardButton -> RequestContactKeyboardButton.serializer().serialize(encoder, obj) + is RequestLocationKeyboardButton -> RequestLocationKeyboardButton.serializer().serialize(encoder, obj) + is RequestPollKeyboardButton -> RequestPollKeyboardButton.serializer().serialize(encoder, obj) + is SimpleKeyboardButton -> encoder.encodeString(obj.text) + is UnknownKeyboardButton -> JsonElementSerializer.serialize(encoder, Json.nonstrict.parseJson(obj.raw)) + } + } +} + diff --git a/src/commonMain/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/buttons/KeyboardButtonPollType.kt b/src/commonMain/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/buttons/KeyboardButtonPollType.kt new file mode 100644 index 0000000000..e657c732d3 --- /dev/null +++ b/src/commonMain/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/buttons/KeyboardButtonPollType.kt @@ -0,0 +1,49 @@ +package com.github.insanusmokrassar.TelegramBotAPI.types.buttons + +import com.github.insanusmokrassar.TelegramBotAPI.types.* +import kotlinx.serialization.* +import kotlinx.serialization.json.* + +@Serializable(KeyboardButtonPollTypeSerializer::class) +sealed class KeyboardButtonPollType { + abstract val type: String +} + +@Serializable +class UnknownKeyboardButtonPollType internal constructor(override val type: String): KeyboardButtonPollType() + +@Serializable +object RegularKeyboardButtonPollType : KeyboardButtonPollType() { + override val type: String = regularPollType +} + +@Serializable +object QuizKeyboardButtonPollType : KeyboardButtonPollType() { + override val type: String = quizPollType +} + +@Serializer(KeyboardButtonPollType::class) +internal object KeyboardButtonPollTypeSerializer : KSerializer { + override fun deserialize(decoder: Decoder): KeyboardButtonPollType { + val asJson = JsonElementSerializer.deserialize(decoder) + + val type = when (asJson) { + is JsonPrimitive -> asJson.content + else -> asJson.jsonObject.getPrimitive(typeField).content + } + + return when (type) { + regularPollType -> RegularKeyboardButtonPollType + quizPollType -> QuizKeyboardButtonPollType + else -> UnknownKeyboardButtonPollType(type) + } + } + + override fun serialize(encoder: Encoder, obj: KeyboardButtonPollType) { + when (obj) { + RegularKeyboardButtonPollType -> RegularKeyboardButtonPollType.serializer().serialize(encoder, RegularKeyboardButtonPollType) + QuizKeyboardButtonPollType -> QuizKeyboardButtonPollType.serializer().serialize(encoder, QuizKeyboardButtonPollType) + is UnknownKeyboardButtonPollType -> UnknownKeyboardButtonPollType.serializer().serialize(encoder, obj) + } + } +}