mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2024-09-20 17:46:08 +00:00
202 lines
9.4 KiB
Kotlin
202 lines
9.4 KiB
Kotlin
package dev.inmo.tgbotapi.types.buttons
|
|
|
|
import dev.inmo.tgbotapi.types.*
|
|
import dev.inmo.tgbotapi.types.webapps.WebAppInfo
|
|
import dev.inmo.tgbotapi.utils.RiskFeature
|
|
import dev.inmo.tgbotapi.utils.nonstrictJsonFormat
|
|
import kotlinx.serialization.*
|
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
|
import kotlinx.serialization.encoding.Decoder
|
|
import kotlinx.serialization.encoding.Encoder
|
|
import kotlinx.serialization.json.*
|
|
|
|
/**
|
|
* Representation union of https://core.telegram.org/bots/api#keyboardbutton . See inheritors for more info
|
|
*/
|
|
@Serializable(KeyboardButtonSerializer::class)
|
|
sealed interface KeyboardButton {
|
|
val text: String
|
|
}
|
|
|
|
/**
|
|
* Simple button. user will send text of this button. You will be able to catch this text in updates and data using
|
|
* [dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onText] in
|
|
* case you are using Behaviour Builder OR with [dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter.messagesFlow]
|
|
* and [kotlinx.coroutines.flow.filterIsInstance] and filtering by type
|
|
* [dev.inmo.tgbotapi.types.message.abstracts.CommonMessage] and [dev.inmo.tgbotapi.extensions.utils.onlyTextContentMessages]
|
|
*/
|
|
@Serializable
|
|
data class SimpleKeyboardButton(
|
|
override val text: String
|
|
) : KeyboardButton
|
|
|
|
@Serializable
|
|
data class UnknownKeyboardButton internal constructor(
|
|
override val text: String,
|
|
val raw: String
|
|
) : KeyboardButton
|
|
|
|
/**
|
|
* Private chats only. When user will tap on this button, his contact (with his number and name) will be sent to the bot. You will be able
|
|
* to catch this contact in updates and data using [dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onContact] in
|
|
* case you are using Behaviour Builder OR with [dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter.messagesFlow]
|
|
* and [kotlinx.coroutines.flow.filterIsInstance] and filtering by type
|
|
* [dev.inmo.tgbotapi.types.message.abstracts.CommonMessage] and [dev.inmo.tgbotapi.extensions.utils.onlyContactContentMessages]
|
|
*/
|
|
@Serializable
|
|
data class RequestContactKeyboardButton(
|
|
override val text: String
|
|
) : KeyboardButton {
|
|
@SerialName(requestContactField)
|
|
@EncodeDefault
|
|
val requestContact: Boolean = true
|
|
}
|
|
|
|
/**
|
|
* Private chats only. When user will tap on this button, his location will be sent to the bot. You will be able
|
|
* to catch this location in updates and data using [dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onLocation] in
|
|
* case you are using Behaviour Builder OR with [dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter.messagesFlow]
|
|
* and [kotlinx.coroutines.flow.filterIsInstance] and filtering by type
|
|
* [dev.inmo.tgbotapi.types.message.abstracts.CommonMessage] and [dev.inmo.tgbotapi.extensions.utils.onlyLocationContentMessages]
|
|
*/
|
|
@Serializable
|
|
data class RequestLocationKeyboardButton(
|
|
override val text: String
|
|
) : KeyboardButton {
|
|
@SerialName(requestLocationField)
|
|
@Required
|
|
val requestLocation: Boolean = true
|
|
}
|
|
|
|
/**
|
|
* Private chats only. Description of the Web App that will be launched when the user presses the button. The Web App
|
|
* will be able to send an arbitrary message on behalf of the user using the method `answerWebAppQuery`. Available only
|
|
* in private chats between a user and the bot.
|
|
*/
|
|
@Serializable
|
|
data class WebAppKeyboardButton(
|
|
override val text: String,
|
|
@SerialName(webAppField)
|
|
val webApp: WebAppInfo
|
|
) : KeyboardButton
|
|
|
|
/**
|
|
* Private chats only. When user will tap on this button, he will be asked for the poll with [requestPoll] options. You will be able
|
|
* to catch this poll in updates and data using [dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onPoll] in
|
|
* case you are using Behaviour Builder OR with [dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter.messagesFlow]
|
|
* and [kotlinx.coroutines.flow.filterIsInstance] and filtering by type
|
|
* [dev.inmo.tgbotapi.types.message.abstracts.CommonMessage] and [dev.inmo.tgbotapi.extensions.utils.onlyPollContentMessages]
|
|
*/
|
|
@Serializable
|
|
data class RequestPollKeyboardButton(
|
|
override val text: String,
|
|
@SerialName(requestPollField)
|
|
val requestPoll: KeyboardButtonPollType
|
|
) : KeyboardButton
|
|
|
|
/**
|
|
* Private chats only. When user will tap on this button, he will be asked for the chat with [requestChat] options. You
|
|
* will be able to catch this [ChatId] in updates and data using
|
|
* [dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onUserShared] in case you are using Behaviour
|
|
* Builder OR with [dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter.messagesFlow]
|
|
* and [kotlinx.coroutines.flow.filterIsInstance].
|
|
*
|
|
* In case you will use [dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onUserShared] it is
|
|
* recommended to use [kotlinx.coroutines.flow.Flow] [kotlinx.coroutines.flow.filter] with checking of incoming
|
|
* [dev.inmo.tgbotapi.types.request.UserShared.requestId]
|
|
*/
|
|
@Serializable
|
|
data class RequestUserKeyboardButton(
|
|
override val text: String,
|
|
@SerialName(requestUserField)
|
|
val requestUser: KeyboardButtonRequestUser
|
|
) : KeyboardButton
|
|
|
|
/**
|
|
* Private chats only. When user will tap on this button, he will be asked for the chat with [requestChat] options. You
|
|
* will be able to catch this [ChatId] in updates and data using
|
|
* [dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onChatShared] in case you are using Behaviour
|
|
* Builder OR with [dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter.messagesFlow]
|
|
* and [kotlinx.coroutines.flow.filterIsInstance].
|
|
*
|
|
* In case you will use [dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onChatShared] it is
|
|
* recommended to use [kotlinx.coroutines.flow.Flow] [kotlinx.coroutines.flow.filter] with checking of incoming
|
|
* [dev.inmo.tgbotapi.types.request.ChatShared.requestId]
|
|
*/
|
|
@Serializable
|
|
data class RequestChatKeyboardButton(
|
|
override val text: String,
|
|
@SerialName(requestChatField)
|
|
val requestChat: KeyboardButtonRequestChat
|
|
) : KeyboardButton
|
|
|
|
@RiskFeature
|
|
object KeyboardButtonSerializer : KSerializer<KeyboardButton> {
|
|
private val internalSerializer = JsonElement.serializer()
|
|
override val descriptor: SerialDescriptor = internalSerializer.descriptor
|
|
|
|
override fun deserialize(decoder: Decoder): KeyboardButton {
|
|
val asJson = internalSerializer.deserialize(decoder)
|
|
|
|
return when {
|
|
asJson is JsonPrimitive -> SimpleKeyboardButton(asJson.content)
|
|
asJson is JsonObject && asJson[requestContactField] != null -> RequestContactKeyboardButton(
|
|
asJson[textField]!!.jsonPrimitive.content
|
|
)
|
|
asJson is JsonObject && asJson[requestLocationField] != null -> RequestLocationKeyboardButton(
|
|
asJson[textField]!!.jsonPrimitive.content
|
|
)
|
|
asJson is JsonObject && asJson[webAppField] != null -> WebAppKeyboardButton(
|
|
asJson[textField]!!.jsonPrimitive.content,
|
|
nonstrictJsonFormat.decodeFromJsonElement(
|
|
WebAppInfo.serializer(),
|
|
asJson[webAppField]!!
|
|
)
|
|
)
|
|
asJson is JsonObject && asJson[requestPollField] != null -> RequestPollKeyboardButton(
|
|
asJson[textField]!!.jsonPrimitive.content,
|
|
nonstrictJsonFormat.decodeFromJsonElement(
|
|
KeyboardButtonPollTypeSerializer,
|
|
asJson[requestPollField] ?.jsonObject ?: buildJsonObject { }
|
|
)
|
|
)
|
|
asJson is JsonObject && asJson[requestUserField] != null -> RequestUserKeyboardButton(
|
|
asJson[textField]!!.jsonPrimitive.content,
|
|
nonstrictJsonFormat.decodeFromJsonElement(
|
|
KeyboardButtonRequestUser.serializer(),
|
|
asJson[requestUserField] ?.jsonObject ?: buildJsonObject { }
|
|
)
|
|
)
|
|
asJson is JsonObject && asJson[requestChatField] != null -> RequestChatKeyboardButton(
|
|
asJson[textField]!!.jsonPrimitive.content,
|
|
nonstrictJsonFormat.decodeFromJsonElement(
|
|
KeyboardButtonRequestChat.serializer(),
|
|
asJson[requestChatField] ?.jsonObject ?: buildJsonObject { }
|
|
)
|
|
)
|
|
else -> UnknownKeyboardButton(
|
|
when (asJson) {
|
|
is JsonObject -> asJson[textField]!!.jsonPrimitive.content
|
|
is JsonArray -> ""
|
|
is JsonPrimitive -> asJson.content
|
|
},
|
|
asJson.toString()
|
|
)
|
|
}
|
|
}
|
|
|
|
override fun serialize(encoder: Encoder, value: KeyboardButton) {
|
|
when (value) {
|
|
is RequestContactKeyboardButton -> RequestContactKeyboardButton.serializer().serialize(encoder, value)
|
|
is RequestLocationKeyboardButton -> RequestLocationKeyboardButton.serializer().serialize(encoder, value)
|
|
is WebAppKeyboardButton -> WebAppKeyboardButton.serializer().serialize(encoder, value)
|
|
is RequestPollKeyboardButton -> RequestPollKeyboardButton.serializer().serialize(encoder, value)
|
|
is SimpleKeyboardButton -> encoder.encodeString(value.text)
|
|
is RequestUserKeyboardButton -> RequestUserKeyboardButton.serializer().serialize(encoder, value)
|
|
is RequestChatKeyboardButton -> RequestChatKeyboardButton.serializer().serialize(encoder, value)
|
|
is UnknownKeyboardButton -> JsonElement.serializer().serialize(encoder, nonstrictJsonFormat.parseToJsonElement(value.raw))
|
|
}
|
|
}
|
|
}
|
|
|