diff --git a/CHANGELOG.md b/CHANGELOG.md index 8dc902d3b9..ee0587f34a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ * `Core`: * `MessageCallbackQuery` (and all implementers as well) has changed the type of `message`: now it is `ContentMessage` instead of `Message` + * New type `ForwardFromPublicChatInfo` as extender of `ForwardInfo`: + * `ForwardFromChannelInfo` now extends `ForwardFromPublicChatInfo` + * `ForwardFromSupergroupInfo` now extends `ForwardFromPublicChatInfo` + * New type of events: `UserLoggedIn` ## 0.38.0 diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitEventAction.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitEventAction.kt index 81672cc796..841f9bcf06 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitEventAction.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitEventAction.kt @@ -234,3 +234,10 @@ suspend fun BehaviourContext.waitSuccessfulPaymentEvents( filter: SimpleFilter>? = null, mapper: EventMessageToEventMapper? = null ) = waitEvents(count, initRequest, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitUserLoggedInEvents( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + filter: SimpleFilter>? = null, + mapper: EventMessageToEventMapper? = null +) = waitEvents(count, initRequest, errorFactory, filter, mapper) diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/EventTriggers.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/EventTriggers.kt index 4fe6b2c3a3..f39245b11d 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/EventTriggers.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/EventTriggers.kt @@ -464,3 +464,22 @@ suspend fun BC.onSuccessfulPayment( markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: CustomBehaviourContextAndTypeReceiver> ) = onEvent(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.onUserLoggedIn( + initialFilter: SimpleFilter>? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/ChatEvents/UserLoggedIn.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/ChatEvents/UserLoggedIn.kt new file mode 100644 index 0000000000..eb21c274e3 --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/ChatEvents/UserLoggedIn.kt @@ -0,0 +1,7 @@ +package dev.inmo.tgbotapi.types.message.ChatEvents + +import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.PrivateEvent + +data class UserLoggedIn( + val domain: String +) : PrivateEvent diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/ForwardInfo.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/ForwardInfo.kt index f239b9d235..8613ff4e43 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/ForwardInfo.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/ForwardInfo.kt @@ -2,8 +2,7 @@ package dev.inmo.tgbotapi.types.message import dev.inmo.tgbotapi.CommonAbstracts.FromUser import dev.inmo.tgbotapi.types.* -import dev.inmo.tgbotapi.types.chat.abstracts.ChannelChat -import dev.inmo.tgbotapi.types.chat.abstracts.SupergroupChat +import dev.inmo.tgbotapi.types.chat.abstracts.* sealed class ForwardInfo { abstract val dateOfOriginal: TelegramDate @@ -19,14 +18,24 @@ data class UserForwardInfo( override val from: User ) : ForwardInfo(), FromUser +sealed class ForwardFromPublicChatInfo : ForwardInfo() { + abstract val chat: PublicChat +} + data class ForwardFromChannelInfo( override val dateOfOriginal: TelegramDate, val messageId: MessageIdentifier, val channelChat: ChannelChat, val signature: String? = null -) : ForwardInfo() +) : ForwardFromPublicChatInfo() { + override val chat: PublicChat + get() = channelChat +} data class ForwardFromSupergroupInfo( override val dateOfOriginal: TelegramDate, val group: SupergroupChat -) : ForwardInfo() +) : ForwardFromPublicChatInfo() { + override val chat: PublicChat + get() = group +} diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/RawMessage.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/RawMessage.kt index e823db8cc2..38868d2ae3 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/RawMessage.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/RawMessage.kt @@ -201,6 +201,7 @@ internal data class RawMessage( pinned_message != null -> PinnedMessage(pinned_message.asMessage) proximity_alert_triggered != null -> proximity_alert_triggered successful_payment != null -> SuccessfulPaymentEvent(successful_payment) + connected_website != null -> UserLoggedIn(connected_website) else -> null } } diff --git a/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ClassCasts.kt b/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ClassCasts.kt index d033cd6421..a9e46e1268 100644 --- a/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ClassCasts.kt +++ b/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ClassCasts.kt @@ -42,6 +42,7 @@ import dev.inmo.tgbotapi.types.message.content.* import dev.inmo.tgbotapi.types.message.content.abstracts.* import dev.inmo.tgbotapi.types.message.content.media.* import dev.inmo.tgbotapi.types.message.payments.InvoiceContent +import dev.inmo.tgbotapi.types.message.payments.SuccessfulPaymentEvent import dev.inmo.tgbotapi.types.passport.* import dev.inmo.tgbotapi.types.passport.decrypted.* import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.* @@ -3064,6 +3065,15 @@ inline fun ChatEvent.asPinnedMessage(): PinnedMessage? = this as? PinnedMessage @PreviewFeature inline fun ChatEvent.requirePinnedMessage(): PinnedMessage = this as PinnedMessage +@PreviewFeature +inline fun ChatEvent.whenSuccessfulPaymentEvent(block: (SuccessfulPaymentEvent) -> T) = asSuccessfulPaymentEvent() ?.let(block) + +@PreviewFeature +inline fun ChatEvent.asSuccessfulPaymentEvent(): SuccessfulPaymentEvent? = this as? SuccessfulPaymentEvent + +@PreviewFeature +inline fun ChatEvent.requireSuccessfulPaymentEvent(): SuccessfulPaymentEvent = this as SuccessfulPaymentEvent + @PreviewFeature inline fun ChatEvent.whenProximityAlertTriggered(block: (ProximityAlertTriggered) -> T) = asProximityAlertTriggered() ?.let(block) @@ -3174,6 +3184,24 @@ inline fun ChatEvent.asVoiceChatStarted(): VoiceChatStarted? = this as? VoiceCha @PreviewFeature inline fun ChatEvent.requireVoiceChatStarted(): VoiceChatStarted = this as VoiceChatStarted +@PreviewFeature +inline fun ChatEvent.whenVoiceChatScheduled(block: (VoiceChatScheduled) -> T) = asVoiceChatScheduled() ?.let(block) + +@PreviewFeature +inline fun ChatEvent.asVoiceChatScheduled(): VoiceChatScheduled? = this as? VoiceChatScheduled + +@PreviewFeature +inline fun ChatEvent.requireVoiceChatScheduled(): VoiceChatScheduled = this as VoiceChatScheduled + +@PreviewFeature +inline fun ChatEvent.whenUserLoggedIn(block: (UserLoggedIn) -> T) = asUserLoggedIn() ?.let(block) + +@PreviewFeature +inline fun ChatEvent.asUserLoggedIn(): UserLoggedIn? = this as? UserLoggedIn + +@PreviewFeature +inline fun ChatEvent.requireUserLoggedIn(): UserLoggedIn = this as UserLoggedIn + @PreviewFeature inline fun CommonSendInvoiceData.whenSendInvoice(block: (SendInvoice) -> T) = asSendInvoice() ?.let(block) @@ -3283,3 +3311,57 @@ inline fun ChatInviteLink.asChatInviteLinkUnlimited(): ChatInviteLinkUnlimited? @PreviewFeature inline fun ChatInviteLink.requireChatInviteLinkUnlimited(): ChatInviteLinkUnlimited = this as ChatInviteLinkUnlimited + +@PreviewFeature +inline fun ForwardInfo.whenAnonymousForwardInfo(block: (AnonymousForwardInfo) -> T) = asAnonymousForwardInfo() ?.let(block) + +@PreviewFeature +inline fun ForwardInfo.asAnonymousForwardInfo(): AnonymousForwardInfo? = this as? AnonymousForwardInfo + +@PreviewFeature +inline fun ForwardInfo.requireAnonymousForwardInfo(): AnonymousForwardInfo = this as AnonymousForwardInfo + +@PreviewFeature +inline fun ForwardInfo.whenUserForwardInfo(block: (UserForwardInfo) -> T) = asUserForwardInfo() ?.let(block) + +@PreviewFeature +inline fun ForwardInfo.asUserForwardInfo(): UserForwardInfo? = this as? UserForwardInfo + +@PreviewFeature +inline fun ForwardInfo.requireUserForwardInfo(): UserForwardInfo = this as UserForwardInfo + +@PreviewFeature +inline fun ForwardInfo.whenForwardFromPublicChatInfo(block: (ForwardFromPublicChatInfo) -> T) = asForwardFromPublicChatInfo() ?.let(block) + +@PreviewFeature +inline fun ForwardInfo.asForwardFromPublicChatInfo(): ForwardFromPublicChatInfo? = this as? ForwardFromPublicChatInfo + +@PreviewFeature +inline fun ForwardInfo.requireForwardFromPublicChatInfo(): ForwardFromPublicChatInfo = this as ForwardFromPublicChatInfo + +@PreviewFeature +inline fun ForwardInfo.whenForwardFromChannelInfo(block: (ForwardFromChannelInfo) -> T) = asForwardFromChannelInfo() ?.let(block) + +@PreviewFeature +inline fun ForwardInfo.asForwardFromChannelInfo(): ForwardFromChannelInfo? = this as? ForwardFromChannelInfo + +@PreviewFeature +inline fun ForwardInfo.requireForwardFromChannelInfo(): ForwardFromChannelInfo = this as ForwardFromChannelInfo + +@PreviewFeature +inline fun ForwardInfo.whenForwardFromSupergroupInfo(block: (ForwardFromSupergroupInfo) -> T) = asForwardFromSupergroupInfo() ?.let(block) + +@PreviewFeature +inline fun ForwardInfo.asForwardFromSupergroupInfo(): ForwardFromSupergroupInfo? = this as? ForwardFromSupergroupInfo + +@PreviewFeature +inline fun ForwardInfo.requireForwardFromSupergroupInfo(): ForwardFromSupergroupInfo = this as ForwardFromSupergroupInfo + +@PreviewFeature +inline fun MessageContent.whenTextedInput(block: (TextedInput) -> T) = asTextedInput() ?.let(block) + +@PreviewFeature +inline fun MessageContent.asTextedInput(): TextedInput? = this as? TextedInput + +@PreviewFeature +inline fun MessageContent.requireTextedInput(): TextedInput = this as TextedInput diff --git a/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/extensions/raw/Message.kt b/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/extensions/raw/Message.kt new file mode 100644 index 0000000000..fc039a7085 --- /dev/null +++ b/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/extensions/raw/Message.kt @@ -0,0 +1,211 @@ +package dev.inmo.tgbotapi.extensions.utils.extensions.raw + +import dev.inmo.tgbotapi.CommonAbstracts.FromUser +import dev.inmo.tgbotapi.extensions.utils.* +import dev.inmo.tgbotapi.types.* +import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList +import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup +import dev.inmo.tgbotapi.types.chat.abstracts.Chat +import dev.inmo.tgbotapi.types.chat.abstracts.PublicChat +import dev.inmo.tgbotapi.types.dice.Dice +import dev.inmo.tgbotapi.types.files.* +import dev.inmo.tgbotapi.types.games.Game +import dev.inmo.tgbotapi.types.location.Location +import dev.inmo.tgbotapi.types.message.ChatEvents.* +import dev.inmo.tgbotapi.types.message.ChatEvents.voice.* +import dev.inmo.tgbotapi.types.message.abstracts.ConnectedFromChannelGroupContentMessage +import dev.inmo.tgbotapi.types.message.abstracts.Message +import dev.inmo.tgbotapi.types.message.content.TextContent +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.venue.Venue +import dev.inmo.tgbotapi.utils.RiskFeature + +private const val RawFieldsUsageWarning = "This API is raw and experimental. So, it is possible that behaviour of this API will be changed in near updates" + +@RiskFeature(RawFieldsUsageWarning) +inline val Message.from: User? + get() = asFromUser() ?.from +@RiskFeature(RawFieldsUsageWarning) +inline val Message.sender_chat: PublicChat? + get() = asFromChannelGroupContentMessage() ?.senderChat +@RiskFeature(RawFieldsUsageWarning) +inline val Message.forward_from: User? + get() = asPossiblyForwardedMessage() ?.forwardInfo ?.asUserForwardInfo() ?.from +@RiskFeature(RawFieldsUsageWarning) +inline val Message.forward_from_chat: Chat? + get() = asPossiblyForwardedMessage() ?.forwardInfo ?.asForwardFromPublicChatInfo() ?.chat +@RiskFeature(RawFieldsUsageWarning) +inline val Message.forward_from_message_id: MessageIdentifier? + get() = asPossiblyForwardedMessage() ?.forwardInfo ?.asForwardFromChannelInfo() ?.messageId +@RiskFeature(RawFieldsUsageWarning) +inline val Message.forward_signature: ForwardSignature? + get() = asPossiblyForwardedMessage() ?.forwardInfo ?.asForwardFromChannelInfo() ?.signature +@RiskFeature(RawFieldsUsageWarning) +inline val Message.forward_sender_name: ForwardSenderName? + get() = asPossiblyForwardedMessage() ?.forwardInfo ?.asAnonymousForwardInfo() ?.senderName +@RiskFeature(RawFieldsUsageWarning) +inline val Message.forward_date: TelegramDate? + get() = asPossiblyForwardedMessage() ?.forwardInfo ?.dateOfOriginal +@RiskFeature(RawFieldsUsageWarning) +inline val Message.is_automatic_forward: Boolean? + get() = this is ConnectedFromChannelGroupContentMessage<*> +@RiskFeature(RawFieldsUsageWarning) +inline val Message.reply_to_message: Message? + get() = asPossiblyReplyMessage() ?.replyTo +@RiskFeature(RawFieldsUsageWarning) +inline val Message.via_bot: CommonBot? + get() = asPossiblySentViaBotCommonMessage() ?.senderBot +@RiskFeature(RawFieldsUsageWarning) +inline val Message.edit_date: TelegramDate? + get() = asPossiblyEditedMessage() ?.editDate ?.toTelegramDate() +@RiskFeature(RawFieldsUsageWarning) +inline val Message.has_protected_content: Boolean? + get() = asContentMessage() ?.hasProtectedContent +@RiskFeature(RawFieldsUsageWarning) +inline val Message.media_group_id: MediaGroupIdentifier? + get() = asMediaGroupMessage() ?.mediaGroupId +@RiskFeature(RawFieldsUsageWarning) +inline val Message.author_signature: AuthorSignature? + get() = asSignedMessage() ?.authorSignature +@RiskFeature(RawFieldsUsageWarning) +inline val Message.text: String? + get() = asContentMessage() ?.content ?.asTextContent() ?.text +@RiskFeature(RawFieldsUsageWarning) +inline val Message.entities: TextSourcesList? + get() = asContentMessage() ?.content ?.asTextContent() ?.textSources +@RiskFeature(RawFieldsUsageWarning) +inline val Message.caption: String? + get() = whenContentMessage { + if (it.content !is TextContent) { + it.content.asTextedInput() ?.text + } else { + null + } + } +@RiskFeature(RawFieldsUsageWarning) +inline val Message.caption_entities: TextSourcesList? + get() = whenContentMessage { + if (it.content !is TextContent) { + it.content.asTextedInput() ?.textSources + } else { + null + } + } +@RiskFeature(RawFieldsUsageWarning) +inline val Message.audio: AudioFile? + get() = asContentMessage() ?.content ?.asAudioContent() ?.media +@RiskFeature(RawFieldsUsageWarning) +inline val Message.document: DocumentFile? + get() = asContentMessage() ?.content ?.asDocumentContent() ?.media +@RiskFeature(RawFieldsUsageWarning) +inline val Message.animation: AnimationFile? + get() = asContentMessage() ?.content ?.asAnimationContent() ?.media +@RiskFeature(RawFieldsUsageWarning) +inline val Message.game: Game? + get() = asContentMessage() ?.content ?.asGameContent() ?.game +@RiskFeature(RawFieldsUsageWarning) +inline val Message.photo: Photo? + get() = asContentMessage() ?.content ?.asPhotoContent() ?.mediaCollection +@RiskFeature(RawFieldsUsageWarning) +inline val Message.sticker: Sticker? + get() = asContentMessage() ?.content ?.asStickerContent() ?.media +@RiskFeature(RawFieldsUsageWarning) +inline val Message.video: VideoFile? + get() = asContentMessage() ?.content ?.asVideoContent() ?.media +@RiskFeature(RawFieldsUsageWarning) +inline val Message.voice: VoiceFile? + get() = asContentMessage() ?.content ?.asVoiceContent() ?.media +@RiskFeature(RawFieldsUsageWarning) +inline val Message.video_note: VideoNoteFile? + get() = asContentMessage() ?.content ?.asVideoNoteContent() ?.media +@RiskFeature(RawFieldsUsageWarning) +inline val Message.contact: Contact? + get() = asContentMessage() ?.content ?.asContactContent() ?.contact +@RiskFeature(RawFieldsUsageWarning) +inline val Message.location: Location? + get() = asContentMessage() ?.content ?.asLocationContent() ?.location +@RiskFeature(RawFieldsUsageWarning) +inline val Message.venue: Venue? + get() = asContentMessage() ?.content ?.asVenueContent() ?.venue +@RiskFeature(RawFieldsUsageWarning) +inline val Message.poll: Poll? + get() = asContentMessage() ?.content ?.asPollContent() ?.poll +@RiskFeature(RawFieldsUsageWarning) +inline val Message.invoice: Invoice? + get() = asContentMessage() ?.content ?.asInvoiceContent() ?.invoice +@RiskFeature(RawFieldsUsageWarning) +inline val Message.dice: Dice? + get() = asContentMessage() ?.content ?.asDiceContent() ?.dice +@RiskFeature(RawFieldsUsageWarning) +inline val Message.new_chat_members: List? + get() = asChatEventMessage() ?.chatEvent ?.asNewChatMembers() ?.members +@RiskFeature(RawFieldsUsageWarning) +inline val Message.left_chat_member: User? + get() = asChatEventMessage() ?.chatEvent ?.asLeftChatMember() ?.user +@RiskFeature(RawFieldsUsageWarning) +inline val Message.new_chat_title: String? + get() = asChatEventMessage() ?.chatEvent ?.asNewChatTitle() ?.title +@RiskFeature(RawFieldsUsageWarning) +inline val Message.new_chat_photo: Photo? + get() = asChatEventMessage() ?.chatEvent ?.asNewChatPhoto() ?.photo +@RiskFeature(RawFieldsUsageWarning) +inline val Message.delete_chat_photo: Boolean + get() = asChatEventMessage() ?.chatEvent is DeleteChatPhoto +@RiskFeature(RawFieldsUsageWarning) +inline val Message.group_chat_created: Boolean + get() = asChatEventMessage() ?.chatEvent is GroupChatCreated +@RiskFeature(RawFieldsUsageWarning) +inline val Message.supergroup_chat_created: Boolean + get() = asChatEventMessage() ?.chatEvent is SupergroupChatCreated +@RiskFeature(RawFieldsUsageWarning) +inline val Message.channel_chat_created: Boolean + get() = asChatEventMessage() ?.chatEvent is ChannelChatCreated +@RiskFeature(RawFieldsUsageWarning) +inline val Message.migrate_to_chat_id: ChatId? + get() = asChatEventMessage() ?.chatEvent ?.asGroupChatCreated() ?.migratedTo +@RiskFeature(RawFieldsUsageWarning) +inline val Message.migrate_from_chat_id: ChatId? + get() = asChatEventMessage() ?.chatEvent ?.let { + it ?.asSupergroupChatCreated() ?.migratedFrom ?: it ?.asMigratedToSupergroup() ?.migratedFrom + } +@RiskFeature(RawFieldsUsageWarning) +inline val Message.pinned_message: Message? + get() = asChatEventMessage() ?.chatEvent ?.asPinnedMessage() ?.message +@RiskFeature(RawFieldsUsageWarning) +inline val Message.successful_payment: SuccessfulPayment? + get() = asChatEventMessage() ?.chatEvent ?.asSuccessfulPaymentEvent() ?.payment + +@RiskFeature(RawFieldsUsageWarning) +inline val Message.voice_chat_scheduled: VoiceChatScheduled? + get() = asChatEventMessage() ?.chatEvent ?.asVoiceChatScheduled() +@RiskFeature(RawFieldsUsageWarning) +inline val Message.voice_chat_started: VoiceChatStarted? + get() = asChatEventMessage() ?.chatEvent ?.asVoiceChatStarted() +@RiskFeature(RawFieldsUsageWarning) +inline val Message.voice_chat_ended: VoiceChatEnded? + get() = asChatEventMessage() ?.chatEvent ?.asVoiceChatEnded() +@RiskFeature(RawFieldsUsageWarning) +inline val Message.voice_chat_participants_invited: VoiceChatParticipantsInvited? + get() = asChatEventMessage() ?.chatEvent ?.asVoiceChatParticipantsInvited() + +@RiskFeature(RawFieldsUsageWarning) +inline val Message.message_auto_delete_timer_changed: MessageAutoDeleteTimerChanged? + get() = asChatEventMessage() ?.chatEvent ?.asMessageAutoDeleteTimerChanged() + +@RiskFeature(RawFieldsUsageWarning) +inline val Message.connected_website: String? + get() = asChatEventMessage() ?.chatEvent ?.asUserLoggedIn() ?.domain +@RiskFeature(RawFieldsUsageWarning) +inline val Message.proximity_alert_triggered: ProximityAlertTriggered? + get() = asChatEventMessage() ?.chatEvent ?.asProximityAlertTriggered() + +@RiskFeature(RawFieldsUsageWarning) +inline val Message.passport_data: PassportData? + get() = asPassportMessage() ?.passportData + +@RiskFeature(RawFieldsUsageWarning) +inline val Message.reply_markup: InlineKeyboardMarkup? + get() = asCommonMessage() ?.replyMarkup