support of user shared/chat shared

This commit is contained in:
InsanusMokrassar 2023-02-05 20:46:12 +06:00
parent 6dbe5f024f
commit 687f9e95fa
15 changed files with 581 additions and 0 deletions

View File

@ -17,6 +17,9 @@ import dev.inmo.tgbotapi.types.message.ChatEvents.forum.WriteAccessAllowed
import dev.inmo.tgbotapi.types.message.ChatEvents.voice.*
import dev.inmo.tgbotapi.types.message.abstracts.ChatEventMessage
import dev.inmo.tgbotapi.types.message.payments.SuccessfulPaymentEvent
import dev.inmo.tgbotapi.types.request.ChatShared
import dev.inmo.tgbotapi.types.request.ChatSharedRequest
import dev.inmo.tgbotapi.types.request.UserShared
import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.lowLevelRiskFeatureMessage
import kotlinx.coroutines.flow.Flow
@ -171,3 +174,18 @@ suspend fun BehaviourContext.waitWriteAccessAllowed(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEvents<WriteAccessAllowed>(initRequest, errorFactory)
suspend fun BehaviourContext.waitChatSharedRequest(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEvents<ChatSharedRequest>(initRequest, errorFactory)
suspend fun BehaviourContext.waitUserShared(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEvents<UserShared>(initRequest, errorFactory)
suspend fun BehaviourContext.waitChatShared(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEvents<ChatShared>(initRequest, errorFactory)

View File

@ -9,10 +9,17 @@ import dev.inmo.tgbotapi.types.message.ChatEvents.*
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.*
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicClosed
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicCreated
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicEdited
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicReopened
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.GeneralForumTopicHidden
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.GeneralForumTopicUnhidden
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.WriteAccessAllowed
import dev.inmo.tgbotapi.types.message.ChatEvents.voice.*
import dev.inmo.tgbotapi.types.message.abstracts.ChatEventMessage
import dev.inmo.tgbotapi.types.message.payments.SuccessfulPaymentEvent
import dev.inmo.tgbotapi.types.request.ChatShared
import dev.inmo.tgbotapi.types.request.ChatSharedRequest
import dev.inmo.tgbotapi.types.request.UserShared
import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.lowLevelRiskFeatureMessage
import kotlinx.coroutines.flow.Flow
@ -148,3 +155,34 @@ suspend fun BehaviourContext.waitForumTopicReopenedEventsMessages(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEventsMessages<ForumTopicReopened>(initRequest, errorFactory)
suspend fun BehaviourContext.waitForumTopicEditedEventsMessages(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEventsMessages<ForumTopicEdited>(initRequest, errorFactory)
suspend fun BehaviourContext.waitGeneralForumTopicHiddenEventsMessages(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEventsMessages<GeneralForumTopicHidden>(initRequest, errorFactory)
suspend fun BehaviourContext.waitGeneralForumTopicUnhiddenEventsMessages(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEventsMessages<GeneralForumTopicUnhidden>(initRequest, errorFactory)
suspend fun BehaviourContext.waitWriteAccessAllowedEventsMessages(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEventsMessages<WriteAccessAllowed>(initRequest, errorFactory)
suspend fun BehaviourContext.waitChatSharedRequestEventsMessages(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEventsMessages<ChatSharedRequest>(initRequest, errorFactory)
suspend fun BehaviourContext.waitUserSharedEventsMessages(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEventsMessages<UserShared>(initRequest, errorFactory)
suspend fun BehaviourContext.waitChatSharedEventsMessages(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEventsMessages<ChatShared>(initRequest, errorFactory)

View File

@ -23,6 +23,9 @@ import dev.inmo.tgbotapi.types.message.PrivateEventMessage
import dev.inmo.tgbotapi.types.message.abstracts.ChatEventMessage
import dev.inmo.tgbotapi.types.message.abstracts.SupergroupEventMessage
import dev.inmo.tgbotapi.types.message.payments.SuccessfulPaymentEvent
import dev.inmo.tgbotapi.types.request.ChatShared
import dev.inmo.tgbotapi.types.request.ChatSharedRequest
import dev.inmo.tgbotapi.types.request.UserShared
import dev.inmo.tgbotapi.types.update.abstracts.Update
internal suspend inline fun <BC : BehaviourContext, reified T : ChatEvent> BC.onEvent(
@ -657,3 +660,65 @@ suspend fun <BC : BehaviourContext> BC.onWriteAccessAllowed(
markerFactory: MarkerFactory<in ChatEventMessage<WriteAccessAllowed>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, SupergroupEventMessage<WriteAccessAllowed>>
) = onEventWithCustomChatEventMessage(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param markerFactory Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun <BC : BehaviourContext> BC.onChatSharedRequest(
initialFilter: SimpleFilter<PrivateEventMessage<ChatSharedRequest>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, PrivateEventMessage<ChatSharedRequest>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<ChatSharedRequest>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, PrivateEventMessage<ChatSharedRequest>>
) = onEventWithCustomChatEventMessage(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param markerFactory Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun <BC : BehaviourContext> BC.onUserShared(
initialFilter: SimpleFilter<PrivateEventMessage<UserShared>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, PrivateEventMessage<UserShared>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<UserShared>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, PrivateEventMessage<UserShared>>
) = onEventWithCustomChatEventMessage(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param markerFactory Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun <BC : BehaviourContext> BC.onChatShared(
initialFilter: SimpleFilter<PrivateEventMessage<ChatShared>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, PrivateEventMessage<ChatShared>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<ChatShared>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, PrivateEventMessage<ChatShared>>
) = onEventWithCustomChatEventMessage(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)

View File

@ -261,6 +261,19 @@ const val iconColorField = "icon_color"
const val requestContactField = "request_contact"
const val requestLocationField = "request_location"
const val requestPollField = "request_poll"
const val requestUserField = "request_user"
const val requestChatField = "request_chat"
const val requestIdField = "request_id"
const val userIsBotField = "user_is_bot"
const val userIsPremiumField = "user_is_premium"
const val chatIsChannelField = "chat_is_channel"
const val chatIsForumField = "chat_is_forum"
const val chatHasUsernameField = "chat_has_username"
const val chatIsCreatedField = "chat_is_created"
const val userAdministratorRightsField = "user_administrator_rights"
const val botAdministratorRightsField = "bot_administrator_rights"
const val botIsMemberField = "bot_is_member"
const val fileNameField = "file_name"
const val mimeTypeField = "mime_type"

View File

@ -94,6 +94,42 @@ data class RequestPollKeyboardButton(
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()
@ -124,6 +160,20 @@ object KeyboardButtonSerializer : KSerializer<KeyboardButton> {
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
@ -142,6 +192,8 @@ object KeyboardButtonSerializer : KSerializer<KeyboardButton> {
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))
}
}

View File

@ -0,0 +1,38 @@
package dev.inmo.tgbotapi.types.buttons
import dev.inmo.tgbotapi.types.botAdministratorRightsField
import dev.inmo.tgbotapi.types.botIsMemberField
import dev.inmo.tgbotapi.types.chat.member.ChatAdministratorRights
import dev.inmo.tgbotapi.types.chatHasUsernameField
import dev.inmo.tgbotapi.types.chatIsChannelField
import dev.inmo.tgbotapi.types.chatIsCreatedField
import dev.inmo.tgbotapi.types.chatIsForumField
import dev.inmo.tgbotapi.types.request.RequestId
import dev.inmo.tgbotapi.types.requestIdField
import dev.inmo.tgbotapi.types.userAdministratorRightsField
import kotlinx.serialization.EncodeDefault
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
@Serializable
data class KeyboardButtonRequestChat(
@SerialName(requestIdField)
val requestId: RequestId,
@SerialName(chatIsChannelField)
val isChannel: Boolean? = null,
@SerialName(chatIsForumField)
val isForum: Boolean? = null,
@SerialName(chatHasUsernameField)
val withUsername: Boolean? = null,
@SerialName(chatIsCreatedField)
val ownedBy: Boolean? = null,
@SerialName(userAdministratorRightsField)
val userRightsInChat: ChatAdministratorRights? = null,
@SerialName(botAdministratorRightsField)
val botRightsInChat: ChatAdministratorRights? = null,
@SerialName(botIsMemberField)
val botIsMember: Boolean = false
)

View File

@ -0,0 +1,89 @@
package dev.inmo.tgbotapi.types.buttons
import dev.inmo.tgbotapi.types.request.RequestId
import dev.inmo.tgbotapi.types.requestIdField
import dev.inmo.tgbotapi.types.userIsBotField
import dev.inmo.tgbotapi.types.userIsPremiumField
import kotlinx.serialization.EncodeDefault
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.Serializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
@Serializable(KeyboardButtonRequestUser.Companion::class)
sealed interface KeyboardButtonRequestUser {
val requestId: RequestId
val isBot: Boolean?
@Serializable
data class Any(
@SerialName(requestIdField)
override val requestId: RequestId
) : KeyboardButtonRequestUser {
@SerialName(userIsBotField)
@EncodeDefault
override val isBot: Boolean? = null
}
@Serializable
data class Common(
@SerialName(requestIdField)
override val requestId: RequestId,
@SerialName(userIsPremiumField)
val isPremium: Boolean? = null
) : KeyboardButtonRequestUser {
@SerialName(userIsBotField)
@EncodeDefault
override val isBot: Boolean = false
}
@Serializable
data class Bot(
@SerialName(requestIdField)
override val requestId: RequestId
) : KeyboardButtonRequestUser {
@SerialName(userIsBotField)
@EncodeDefault
override val isBot: Boolean = true
}
@Serializer(KeyboardButtonRequestUser::class)
companion object : KSerializer<KeyboardButtonRequestUser> {
@Serializable
private data class Surrogate(
@SerialName(requestIdField)
val requestId: RequestId,
@SerialName(userIsBotField)
val userIsBot: Boolean? = null,
@SerialName(userIsPremiumField)
val userIsPremium: Boolean? = null
)
private val realSerializer = Surrogate.serializer()
override val descriptor: SerialDescriptor = realSerializer.descriptor
override fun deserialize(decoder: Decoder): KeyboardButtonRequestUser {
val surrogate = realSerializer.deserialize(decoder)
return when (surrogate.userIsBot) {
true -> Bot(surrogate.requestId)
false -> Common(surrogate.requestId, surrogate.userIsPremium)
null -> Any(surrogate.requestId)
}
}
override fun serialize(encoder: Encoder, value: KeyboardButtonRequestUser) {
realSerializer.serialize(
encoder,
Surrogate(
value.requestId,
value.isBot,
(value as? Common) ?.isPremium
)
)
}
}
}

View File

@ -2,6 +2,8 @@ package dev.inmo.tgbotapi.types.buttons.reply
import dev.inmo.tgbotapi.types.buttons.*
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.*
import dev.inmo.tgbotapi.types.chat.member.ChatAdministratorRights
import dev.inmo.tgbotapi.types.request.RequestId
import dev.inmo.tgbotapi.types.webapps.WebAppInfo
@ -67,3 +69,99 @@ inline fun webAppReplyButton(
text: String,
url: String
) = webAppReplyButton(text, WebAppInfo(url))
/**
* Creates and put [RequestUserKeyboardButton]
*
* @see replyKeyboard
* @see ReplyKeyboardBuilder.row
*/
inline fun requestUserReplyButton(
text: String,
requestUser: KeyboardButtonRequestUser
) = RequestUserKeyboardButton(
text,
requestUser
)
/**
* Creates and put [RequestUserKeyboardButton] with [KeyboardButtonRequestUser.Bot]
*
* @see replyKeyboard
* @see ReplyKeyboardBuilder.row
*/
inline fun requestBotReplyButton(
text: String,
requestId: RequestId
) = requestUserReplyButton(
text,
KeyboardButtonRequestUser.Bot(requestId)
)
/**
* Creates and put [RequestUserKeyboardButton] with [KeyboardButtonRequestUser.Common]
*
* @see replyKeyboard
* @see ReplyKeyboardBuilder.row
*/
inline fun requestUserReplyButton(
text: String,
requestId: RequestId,
premiumUser: Boolean? = null
) = requestUserReplyButton(
text,
KeyboardButtonRequestUser.Common(requestId, premiumUser)
)
/**
* Creates and put [RequestUserKeyboardButton] with [KeyboardButtonRequestUser.Any]
*
* @see replyKeyboard
* @see ReplyKeyboardBuilder.row
*/
inline fun requestUserOrBotReplyButton(
text: String,
requestId: RequestId
) = requestUserReplyButton(
text,
KeyboardButtonRequestUser.Any(requestId)
)
/**
* Creates and put [RequestChatKeyboardButton]
*
* @see replyKeyboard
* @see ReplyKeyboardBuilder.row
*/
inline fun requestChatReplyButton(
text: String,
requestChat: KeyboardButtonRequestChat
) = RequestChatKeyboardButton(
text,
requestChat
)
/**
* Creates and put [RequestChatKeyboardButton] with [KeyboardButtonRequestChat]
*
* @see replyKeyboard
* @see ReplyKeyboardBuilder.row
*/
inline fun requestChatReplyButton(
text: String,
requestId: RequestId,
isChannel: Boolean? = null,
isForum: Boolean? = null,
withUsername: Boolean? = null,
ownedBy: Boolean? = null,
userRightsInChat: ChatAdministratorRights? = null,
botRightsInChat: ChatAdministratorRights? = null,
botIsMember: Boolean = false
) = requestChatReplyButton(
text,
KeyboardButtonRequestChat(
requestId, isChannel, isForum, withUsername, ownedBy, userRightsInChat, botRightsInChat, botIsMember
)
)

View File

@ -29,6 +29,8 @@ import dev.inmo.tgbotapi.types.passport.PassportData
import dev.inmo.tgbotapi.types.payments.Invoice
import dev.inmo.tgbotapi.types.payments.SuccessfulPayment
import dev.inmo.tgbotapi.types.polls.Poll
import dev.inmo.tgbotapi.types.request.ChatShared
import dev.inmo.tgbotapi.types.request.UserShared
import dev.inmo.tgbotapi.types.venue.Venue
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@ -93,6 +95,9 @@ internal data class RawMessage(
private val dice: Dice? = null,
private val successful_payment: SuccessfulPayment? = null,
private val user_shared: UserShared? = null,
private val chat_shared: ChatShared? = null,
// Voice Chat Service Messages
private val video_chat_scheduled: VideoChatScheduled? = null,
private val video_chat_started: VideoChatStarted? = null,
@ -249,6 +254,8 @@ internal data class RawMessage(
successful_payment != null -> SuccessfulPaymentEvent(successful_payment)
connected_website != null -> UserLoggedIn(connected_website)
web_app_data != null -> web_app_data
user_shared != null -> user_shared
chat_shared != null -> chat_shared
else -> null
}
}

View File

@ -0,0 +1,17 @@
package dev.inmo.tgbotapi.types.request
import dev.inmo.tgbotapi.types.ChatId
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.chatIdField
import dev.inmo.tgbotapi.types.requestIdField
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class ChatShared(
@SerialName(requestIdField)
override val requestId: RequestId,
@SerialName(chatIdField)
override val chatId: ChatId
) : ChatSharedRequest

View File

@ -0,0 +1,8 @@
package dev.inmo.tgbotapi.types.request
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.PrivateEvent
sealed interface ChatSharedRequest : RequestResponse, PrivateEvent {
val chatId: ChatIdentifier
}

View File

@ -0,0 +1,10 @@
package dev.inmo.tgbotapi.types.request
import kotlinx.serialization.Serializable
import kotlin.jvm.JvmInline
@Serializable
@JvmInline
value class RequestId(
val long: Long
)

View File

@ -0,0 +1,5 @@
package dev.inmo.tgbotapi.types.request
sealed interface RequestResponse {
val requestId: RequestId
}

View File

@ -0,0 +1,19 @@
package dev.inmo.tgbotapi.types.request
import dev.inmo.tgbotapi.types.ChatId
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.requestIdField
import dev.inmo.tgbotapi.types.userIdField
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class UserShared(
@SerialName(requestIdField)
override val requestId: RequestId,
@SerialName(userIdField)
val userId: UserId
) : ChatSharedRequest {
override val chatId: ChatId
get() = userId
}

View File

@ -1,6 +1,10 @@
package dev.inmo.tgbotapi.extensions.utils.types.buttons
import dev.inmo.tgbotapi.types.buttons.*
import dev.inmo.tgbotapi.types.buttons.reply.requestChatReplyButton
import dev.inmo.tgbotapi.types.buttons.reply.requestUserReplyButton
import dev.inmo.tgbotapi.types.chat.member.ChatAdministratorRights
import dev.inmo.tgbotapi.types.request.RequestId
import dev.inmo.tgbotapi.types.webapps.WebAppInfo
import dev.inmo.tgbotapi.utils.*
@ -138,3 +142,103 @@ inline fun ReplyKeyboardRowBuilder.webAppButton(
text: String,
url: String
) = webAppButton(text, WebAppInfo(url))
/**
* Creates and put [RequestUserKeyboardButton]
*
* @see replyKeyboard
* @see ReplyKeyboardBuilder.row
*/
inline fun ReplyKeyboardRowBuilder.requestUserButton(
text: String,
requestUser: KeyboardButtonRequestUser
) = add(
requestUserReplyButton(
text,
requestUser
)
)
/**
* Creates and put [RequestUserKeyboardButton] with [KeyboardButtonRequestUser.Bot]
*
* @see replyKeyboard
* @see ReplyKeyboardBuilder.row
*/
inline fun ReplyKeyboardRowBuilder.requestBotButton(
text: String,
requestId: RequestId
) = requestUserButton(
text,
KeyboardButtonRequestUser.Bot(requestId)
)
/**
* Creates and put [RequestUserKeyboardButton] with [KeyboardButtonRequestUser.Common]
*
* @see replyKeyboard
* @see ReplyKeyboardBuilder.row
*/
inline fun ReplyKeyboardRowBuilder.requestUserButton(
text: String,
requestId: RequestId,
premiumUser: Boolean? = null
) = requestUserButton(
text,
KeyboardButtonRequestUser.Common(requestId, premiumUser)
)
/**
* Creates and put [RequestUserKeyboardButton] with [KeyboardButtonRequestUser.Any]
*
* @see replyKeyboard
* @see ReplyKeyboardBuilder.row
*/
inline fun ReplyKeyboardRowBuilder.requestUserOrBotButton(
text: String,
requestId: RequestId
) = requestUserButton(
text,
KeyboardButtonRequestUser.Any(requestId)
)
/**
* Creates and put [RequestChatKeyboardButton]
*
* @see replyKeyboard
* @see ReplyKeyboardBuilder.row
*/
inline fun ReplyKeyboardRowBuilder.requestChatButton(
text: String,
requestChat: KeyboardButtonRequestChat
) = add(
requestChatReplyButton(
text,
requestChat
)
)
/**
* Creates and put [RequestChatKeyboardButton] with [KeyboardButtonRequestChat]
*
* @see replyKeyboard
* @see ReplyKeyboardBuilder.row
*/
inline fun ReplyKeyboardRowBuilder.requestChatButton(
text: String,
requestId: RequestId,
isChannel: Boolean? = null,
isForum: Boolean? = null,
withUsername: Boolean? = null,
ownedBy: Boolean? = null,
userRightsInChat: ChatAdministratorRights? = null,
botRightsInChat: ChatAdministratorRights? = null,
botIsMember: Boolean = false
) = requestChatButton(
text,
KeyboardButtonRequestChat(
requestId, isChannel, isForum, withUsername, ownedBy, userRightsInChat, botRightsInChat, botIsMember
)
)