From 63975cc88e2744e2d8faf109296c461dd080cdf6 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sun, 31 Dec 2023 16:16:26 +0600 Subject: [PATCH] add workarounds for reactions --- .../WaitChatMessageReactionUpdatedUpdates.kt | 31 ++++ ...ChatMessageReactionsCountUpdatedUpdates.kt | 21 +++ ...atMessageReactionUpdatedUpdatesTriggers.kt | 94 ++++++++++ ...atMessageReactionUpdatedMarkerFactories.kt | 7 + .../kotlin/dev/inmo/tgbotapi/types/Common.kt | 5 + .../dev/inmo/tgbotapi/types/UpdateTypes.kt | 21 +++ .../types/chat/ChatMessageReactionUpdated.kt | 162 ++++++++++++++++++ .../chat/ChatMessageReactionsCountUpdated.kt | 19 ++ .../inmo/tgbotapi/types/reactions/Reaction.kt | 2 +- .../types/reactions/ReactionsCount.kt | 14 ++ .../ChatMessageReactionUpdatedUpdate.kt | 12 ++ .../ChatMessageReactionsCountUpdatedUpdate.kt | 13 ++ .../inmo/tgbotapi/types/update/RawUpdate.kt | 8 +- .../updateshandlers/FlowsUpdatesFilter.kt | 4 + .../extensions/utils/ClassCastsNew.kt | 55 ++++++ .../utils/extensions/UpdateChatRetriever.kt | 4 + 16 files changed, 470 insertions(+), 2 deletions(-) create mode 100644 tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitChatMessageReactionUpdatedUpdates.kt create mode 100644 tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitChatMessageReactionsCountUpdatedUpdates.kt create mode 100644 tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ChatMessageReactionUpdatedUpdatesTriggers.kt create mode 100644 tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/marker_factories/ChatMessageReactionUpdatedMarkerFactories.kt create mode 100644 tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/ChatMessageReactionUpdated.kt create mode 100644 tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/ChatMessageReactionsCountUpdated.kt create mode 100644 tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/reactions/ReactionsCount.kt create mode 100644 tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/update/ChatMessageReactionUpdatedUpdate.kt create mode 100644 tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/update/ChatMessageReactionsCountUpdatedUpdate.kt diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitChatMessageReactionUpdatedUpdates.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitChatMessageReactionUpdatedUpdates.kt new file mode 100644 index 0000000000..70b2307604 --- /dev/null +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitChatMessageReactionUpdatedUpdates.kt @@ -0,0 +1,31 @@ +package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations + +import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext +import dev.inmo.tgbotapi.extensions.utils.chatMessageReactionUpdatedUpdateOrNull +import dev.inmo.tgbotapi.requests.abstracts.Request +import dev.inmo.tgbotapi.types.chat.ChatMessageReactionUpdated +import dev.inmo.tgbotapi.utils.RiskFeature +import dev.inmo.tgbotapi.utils.lowLevelRiskFeatureMessage +import kotlinx.coroutines.flow.Flow + +@RiskFeature(lowLevelRiskFeatureMessage) +suspend inline fun BehaviourContext.waitChatMessageReactionUpdated( + initRequest: Request<*>? = null, + noinline errorFactory: NullableRequestBuilder<*> = { null } +): Flow = expectFlow( + initRequest, + errorFactory +) { + (it.chatMessageReactionUpdatedUpdateOrNull() ?.data as? O).let(::listOfNotNull) +} + +suspend fun BehaviourContext.waitChatMessageReactionUpdatedByUser( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null } +) = waitChatMessageReactionUpdated(initRequest, errorFactory) + + +suspend fun BehaviourContext.waitChatMessageReactionUpdatedByChat( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null } +) = waitChatMessageReactionUpdated(initRequest, errorFactory) diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitChatMessageReactionsCountUpdatedUpdates.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitChatMessageReactionsCountUpdatedUpdates.kt new file mode 100644 index 0000000000..40292de55e --- /dev/null +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitChatMessageReactionsCountUpdatedUpdates.kt @@ -0,0 +1,21 @@ +package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations + +import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext +import dev.inmo.tgbotapi.extensions.utils.chatMessageReactionUpdatedUpdateOrNull +import dev.inmo.tgbotapi.extensions.utils.chatMessageReactionsCountUpdatedUpdateOrNull +import dev.inmo.tgbotapi.requests.abstracts.Request +import dev.inmo.tgbotapi.types.chat.ChatMessageReactionUpdated +import dev.inmo.tgbotapi.types.chat.ChatMessageReactionsCountUpdated +import dev.inmo.tgbotapi.utils.RiskFeature +import dev.inmo.tgbotapi.utils.lowLevelRiskFeatureMessage +import kotlinx.coroutines.flow.Flow + +suspend inline fun BehaviourContext.waitChatMessageReactionsCountUpdated( + initRequest: Request<*>? = null, + noinline errorFactory: NullableRequestBuilder<*> = { null } +): Flow = expectFlow( + initRequest, + errorFactory +) { + (it.chatMessageReactionsCountUpdatedUpdateOrNull() ?.data).let(::listOfNotNull) +} diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ChatMessageReactionUpdatedUpdatesTriggers.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ChatMessageReactionUpdatedUpdatesTriggers.kt new file mode 100644 index 0000000000..fcad229211 --- /dev/null +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ChatMessageReactionUpdatedUpdatesTriggers.kt @@ -0,0 +1,94 @@ +@file:Suppress("unused") + +package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling + +import dev.inmo.tgbotapi.extensions.behaviour_builder.* +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByChatIdChatMessageReactionUpdatedMarkerFactory +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByIdPollMarkerFactory +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory +import dev.inmo.tgbotapi.extensions.utils.chatMessageReactionUpdatedUpdateOrNull +import dev.inmo.tgbotapi.types.chat.ChatMessageReactionUpdated +import dev.inmo.tgbotapi.types.polls.* +import dev.inmo.tgbotapi.types.update.abstracts.Update + +internal suspend inline fun BC.onChatMessageReactionUpdated( + initialFilter: SimpleFilter? = null, + noinline subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver? = null, + markerFactory: MarkerFactory = ByChatIdChatMessageReactionUpdatedMarkerFactory, + noinline scenarioReceiver: CustomBehaviourContextAndTypeReceiver +) = on(markerFactory, initialFilter, subcontextUpdatesFilter, scenarioReceiver) { + (it.chatMessageReactionUpdatedUpdateOrNull() ?.data as? T) ?.let(::listOfNotNull) +} + +/** + * @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.onChatMessageReactionUpdatedByUser( + initialFilter: SimpleFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver? = null, + markerFactory: MarkerFactory = ByChatIdChatMessageReactionUpdatedMarkerFactory, + scenarioReceiver: CustomBehaviourContextAndTypeReceiver +) = onChatMessageReactionUpdated( + 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.onChatMessageReactionUpdatedByChat( + initialFilter: SimpleFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver? = null, + markerFactory: MarkerFactory = ByChatIdChatMessageReactionUpdatedMarkerFactory, + scenarioReceiver: CustomBehaviourContextAndTypeReceiver +) = onChatMessageReactionUpdated( + 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.onChatMessageReactionUpdatedUnknown( + initialFilter: SimpleFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver? = null, + markerFactory: MarkerFactory = ByChatIdChatMessageReactionUpdatedMarkerFactory, + scenarioReceiver: CustomBehaviourContextAndTypeReceiver +) = onChatMessageReactionUpdated( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/marker_factories/ChatMessageReactionUpdatedMarkerFactories.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/marker_factories/ChatMessageReactionUpdatedMarkerFactories.kt new file mode 100644 index 0000000000..aa9c80213d --- /dev/null +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/marker_factories/ChatMessageReactionUpdatedMarkerFactories.kt @@ -0,0 +1,7 @@ +package dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories + +import dev.inmo.tgbotapi.types.chat.ChatMessageReactionUpdated + +object ByChatIdChatMessageReactionUpdatedMarkerFactory : MarkerFactory { + override suspend fun invoke(data: ChatMessageReactionUpdated) = data.chat.id +} 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 b30bc94e4e..43f7e212b6 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 @@ -196,6 +196,7 @@ const val tgWebAppStartParamField = "tgWebAppStartParam" const val chatIdField = "chat_id" const val senderChatIdField = "sender_chat_id" const val messageIdField = "message_id" +const val actorChatField = "actor_chat" const val messageThreadIdField = "message_thread_id" const val mediaGroupIdField = "media_group_id" const val updateIdField = "update_id" @@ -461,6 +462,9 @@ const val fromField = "from" const val userChatIdField = "user_chat_id" const val userField = "user" const val dateField = "date" +const val reactionsField = "reactions" +const val oldReactionField = "old_reaction" +const val newReactionField = "new_reaction" const val chatField = "chat" const val usernameField = "username" const val bioField = "bio" @@ -524,6 +528,7 @@ const val shippingQueryIdField = "shipping_query_id" const val preCheckoutQueryIdField = "pre_checkout_query_id" const val shippingOptionsField = "shipping_options" const val countryCodeField = "country_code" +const val totalCountField = "total_count" const val stateField = "state" const val cityField = "city" const val firstStreetLineField = "street_line1" diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/UpdateTypes.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/UpdateTypes.kt index 2aa6dc43e8..b7fbeaea86 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/UpdateTypes.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/UpdateTypes.kt @@ -14,8 +14,29 @@ const val UPDATE_POLL_ANSWER = "poll_answer" const val UPDATE_MY_CHAT_MEMBER = "my_chat_member" const val UPDATE_CHAT_MEMBER = "chat_member" const val UPDATE_CHAT_JOIN_REQUEST = "chat_join_request" +const val UPDATE_MESSAGE_REACTION = "message_reaction" +const val UPDATE_MESSAGE_REACTION_COUNT = "message_reaction_count" val ALL_UPDATES_LIST = listOf( + UPDATE_MESSAGE, + UPDATE_EDITED_MESSAGE, + UPDATE_CHANNEL_POST, + UPDATE_EDITED_CHANNEL_POST, + UPDATE_CHOSEN_INLINE_RESULT, + UPDATE_INLINE_QUERY, + UPDATE_CALLBACK_QUERY, + UPDATE_SHIPPING_QUERY, + UPDATE_PRE_CHECKOUT_QUERY, + UPDATE_POLL, + UPDATE_POLL_ANSWER, + UPDATE_MY_CHAT_MEMBER, + UPDATE_CHAT_MEMBER, + UPDATE_CHAT_JOIN_REQUEST, + UPDATE_MESSAGE_REACTION, + UPDATE_MESSAGE_REACTION_COUNT +) + +val ALL_UPDATES_LIST_WITHOUT_REACTIONS = listOf( UPDATE_MESSAGE, UPDATE_EDITED_MESSAGE, UPDATE_CHANNEL_POST, diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/ChatMessageReactionUpdated.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/ChatMessageReactionUpdated.kt new file mode 100644 index 0000000000..ba919d69bb --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/ChatMessageReactionUpdated.kt @@ -0,0 +1,162 @@ +package dev.inmo.tgbotapi.types.chat + +import dev.inmo.tgbotapi.types.* +import dev.inmo.tgbotapi.types.reactions.Reaction +import dev.inmo.tgbotapi.utils.internal.ClassCastsIncluded +import kotlinx.serialization.KSerializer +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.json.JsonDecoder +import kotlinx.serialization.json.JsonElement + +@Serializable(ChatMessageReactionUpdated.Companion::class) +@ClassCastsIncluded +sealed interface ChatMessageReactionUpdated { + val chat: PreviewChat + val messageId: MessageIdentifier + val reactedUser: PreviewUser? + val reactedChat: PreviewChat? + val date: TelegramDate + val old: List + val new: List + + @Serializable(Companion::class) + data class ByUser( + @SerialName(chatField) + override val chat: PreviewChat, + @SerialName(messageIdField) + override val messageId: MessageIdentifier, + @SerialName(userField) + override val reactedUser: PreviewUser, + @Serializable(TelegramDateSerializer::class) + @SerialName(dateField) + override val date: TelegramDate, + @SerialName(oldReactionField) + override val old: List, + @SerialName(newReactionField) + override val new: List + ) : ChatMessageReactionUpdated { + override val reactedChat: PreviewChat? + get() = null + } + + @Serializable(Companion::class) + data class ByChat( + @SerialName(chatField) + override val chat: PreviewChat, + @SerialName(messageIdField) + override val messageId: MessageIdentifier, + @SerialName(actorChatField) + override val reactedChat: PreviewChat, + @Serializable(TelegramDateSerializer::class) + @SerialName(dateField) + override val date: TelegramDate, + @SerialName(oldReactionField) + override val old: List, + @SerialName(newReactionField) + override val new: List + ) : ChatMessageReactionUpdated { + override val reactedUser: PreviewUser? + get() = null + } + + @Serializable(Companion::class) + data class Unknown( + @SerialName(chatField) + override val chat: PreviewChat, + @SerialName(messageIdField) + override val messageId: MessageIdentifier, + @SerialName(actorChatField) + override val reactedChat: PreviewChat?, + @SerialName(userField) + override val reactedUser: PreviewUser?, + @Serializable(TelegramDateSerializer::class) + @SerialName(dateField) + override val date: TelegramDate, + @SerialName(oldReactionField) + override val old: List, + @SerialName(newReactionField) + override val new: List, + val source: JsonElement? + ) : ChatMessageReactionUpdated + + @Serializable + data class Surrogate internal constructor( + @SerialName(chatField) + val chat: PreviewChat, + @SerialName(messageIdField) + val messageId: MessageIdentifier, + @SerialName(userField) + val reactedUser: PreviewUser? = null, + @SerialName(actorChatField) + val reactedChat: PreviewChat? = null, + @Serializable(TelegramDateSerializer::class) + @SerialName(dateField) + val date: TelegramDate, + @SerialName(oldReactionField) + val old: List, + @SerialName(newReactionField) + val new: List + ) + + companion object : KSerializer { + override val descriptor: SerialDescriptor + get() = Surrogate.serializer().descriptor + + override fun deserialize(decoder: Decoder): ChatMessageReactionUpdated { + val (surrogate, jsonElement) = if (decoder is JsonDecoder) { + val jsonElement = decoder.decodeJsonElement() + decoder.json.decodeFromJsonElement(Surrogate.serializer(), jsonElement) to jsonElement + } else { + Surrogate.serializer().deserialize(decoder) to null + } + return when { + surrogate.reactedUser != null -> ByUser( + surrogate.chat, + surrogate.messageId, + surrogate.reactedUser, + surrogate.date, + surrogate.old, + surrogate.new + ) + surrogate.reactedChat != null -> ByChat( + surrogate.chat, + surrogate.messageId, + surrogate.reactedChat, + surrogate.date, + surrogate.old, + surrogate.new + ) + else -> Unknown( + surrogate.chat, + surrogate.messageId, + surrogate.reactedUser, + surrogate.reactedChat, + surrogate.date, + surrogate.old, + surrogate.new, + jsonElement + ) + } + } + + override fun serialize(encoder: Encoder, value: ChatMessageReactionUpdated) { + if (value is Unknown && value.source != null) { + JsonElement.serializer().serialize(encoder, value.source) + } else { + Surrogate( + value.chat, + value.messageId, + value.reactedUser, + value.reactedChat, + value.date, + value.old, + value.new + ) + } + } + } +} \ No newline at end of file diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/ChatMessageReactionsCountUpdated.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/ChatMessageReactionsCountUpdated.kt new file mode 100644 index 0000000000..28f440fbd0 --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/ChatMessageReactionsCountUpdated.kt @@ -0,0 +1,19 @@ +package dev.inmo.tgbotapi.types.chat + +import dev.inmo.tgbotapi.types.* +import dev.inmo.tgbotapi.types.reactions.ReactionsCount +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class ChatMessageReactionsCountUpdated( + @SerialName(chatField) + val chat: PreviewChat, + @SerialName(messageIdField) + val messageId: MessageIdentifier, + @Serializable(TelegramDateSerializer::class) + @SerialName(dateField) + val date: TelegramDate, + @SerialName(reactionsField) + val reactions: List +) diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/reactions/Reaction.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/reactions/Reaction.kt index 15aadf8e94..3cb993ed28 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/reactions/Reaction.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/reactions/Reaction.kt @@ -13,7 +13,7 @@ import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.json.JsonDecoder import kotlinx.serialization.json.JsonElement -@Serializable +@Serializable(Reaction.Companion::class) @ClassCastsIncluded sealed interface Reaction { val type: String diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/reactions/ReactionsCount.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/reactions/ReactionsCount.kt new file mode 100644 index 0000000000..3e1bbf5437 --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/reactions/ReactionsCount.kt @@ -0,0 +1,14 @@ +package dev.inmo.tgbotapi.types.reactions + +import dev.inmo.tgbotapi.types.totalCountField +import dev.inmo.tgbotapi.types.typeField +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class ReactionsCount( + @SerialName(typeField) + val reaction: Reaction, + @SerialName(totalCountField) + val count: Int +) diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/update/ChatMessageReactionUpdatedUpdate.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/update/ChatMessageReactionUpdatedUpdate.kt new file mode 100644 index 0000000000..75303b6a6f --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/update/ChatMessageReactionUpdatedUpdate.kt @@ -0,0 +1,12 @@ +package dev.inmo.tgbotapi.types.update + +import dev.inmo.tgbotapi.types.UpdateIdentifier +import dev.inmo.tgbotapi.types.chat.ChatMessageReactionUpdated +import dev.inmo.tgbotapi.types.update.abstracts.Update +import kotlinx.serialization.Serializable + +@Serializable +data class ChatMessageReactionUpdatedUpdate( + override val updateId: UpdateIdentifier, + override val data: ChatMessageReactionUpdated +) : Update \ No newline at end of file diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/update/ChatMessageReactionsCountUpdatedUpdate.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/update/ChatMessageReactionsCountUpdatedUpdate.kt new file mode 100644 index 0000000000..62ed8a6e1b --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/update/ChatMessageReactionsCountUpdatedUpdate.kt @@ -0,0 +1,13 @@ +package dev.inmo.tgbotapi.types.update + +import dev.inmo.tgbotapi.types.UpdateIdentifier +import dev.inmo.tgbotapi.types.chat.ChatMessageReactionUpdated +import dev.inmo.tgbotapi.types.chat.ChatMessageReactionsCountUpdated +import dev.inmo.tgbotapi.types.update.abstracts.Update +import kotlinx.serialization.Serializable + +@Serializable +data class ChatMessageReactionsCountUpdatedUpdate( + override val updateId: UpdateIdentifier, + override val data: ChatMessageReactionsCountUpdated +) : Update \ No newline at end of file diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/update/RawUpdate.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/update/RawUpdate.kt index 20f57940c0..61cee808e6 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/update/RawUpdate.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/update/RawUpdate.kt @@ -5,6 +5,8 @@ import dev.inmo.tgbotapi.types.queries.callback.RawCallbackQuery import dev.inmo.tgbotapi.types.InlineQueries.ChosenInlineResult.RawChosenInlineResult import dev.inmo.tgbotapi.types.InlineQueries.query.RawInlineQuery import dev.inmo.tgbotapi.types.chat.ChatJoinRequest +import dev.inmo.tgbotapi.types.chat.ChatMessageReactionUpdated +import dev.inmo.tgbotapi.types.chat.ChatMessageReactionsCountUpdated import dev.inmo.tgbotapi.types.chat.member.ChatMemberUpdated import dev.inmo.tgbotapi.types.message.abstracts.* import dev.inmo.tgbotapi.types.payments.PreCheckoutQuery @@ -38,7 +40,9 @@ internal data class RawUpdate constructor( private val poll_answer: PollAnswer? = null, private val my_chat_member: ChatMemberUpdated? = null, private val chat_member: ChatMemberUpdated? = null, - private val chat_join_request: ChatJoinRequest? = null + private val chat_join_request: ChatJoinRequest? = null, + private val message_reaction: ChatMessageReactionUpdated? = null, + private val message_reaction_count: ChatMessageReactionsCountUpdated? = null ) { private var initedUpdate: Update? = null /** @@ -65,6 +69,8 @@ internal data class RawUpdate constructor( my_chat_member != null -> MyChatMemberUpdatedUpdate(updateId, my_chat_member) chat_member != null -> CommonChatMemberUpdatedUpdate(updateId, chat_member) chat_join_request != null -> ChatJoinRequestUpdate(updateId, chat_join_request) + message_reaction != null -> ChatMessageReactionUpdatedUpdate(updateId, message_reaction) + message_reaction_count != null -> ChatMessageReactionsCountUpdatedUpdate(updateId, message_reaction_count) else -> UnknownUpdate( updateId, raw diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter.kt index b1e7c195bf..40e1bfd106 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter.kt @@ -37,6 +37,8 @@ interface FlowsUpdatesFilter : UpdatesFilter { val chatMemberUpdatesFlow: Flow val myChatMemberUpdatesFlow: Flow val chatJoinRequestUpdateFlow: Flow + val chatMessageReactionUpdatedUpdateFlow: Flow + val chatMessageReactionsCountUpdatedUpdateFlow: Flow val unknownUpdatesFlow: Flow } @@ -55,6 +57,8 @@ abstract class AbstractFlowsUpdatesFilter : FlowsUpdatesFilter { override val chatMemberUpdatesFlow: Flow by lazy { allUpdatesFlow.filterIsInstance() } override val myChatMemberUpdatesFlow: Flow by lazy { allUpdatesFlow.filterIsInstance() } override val chatJoinRequestUpdateFlow: Flow by lazy { allUpdatesFlow.filterIsInstance() } + override val chatMessageReactionUpdatedUpdateFlow: Flow by lazy { allUpdatesFlow.filterIsInstance() } + override val chatMessageReactionsCountUpdatedUpdateFlow: Flow by lazy { allUpdatesFlow.filterIsInstance() } override val unknownUpdatesFlow: Flow by lazy { allUpdatesFlow.filterIsInstance() } } diff --git a/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ClassCastsNew.kt b/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ClassCastsNew.kt index 932b1e9fc9..97c231c46c 100644 --- a/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ClassCastsNew.kt +++ b/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ClassCastsNew.kt @@ -112,6 +112,7 @@ import dev.inmo.tgbotapi.types.chat.Bot import dev.inmo.tgbotapi.types.chat.ChannelChat import dev.inmo.tgbotapi.types.chat.Chat import dev.inmo.tgbotapi.types.chat.ChatJoinRequest +import dev.inmo.tgbotapi.types.chat.ChatMessageReactionUpdated import dev.inmo.tgbotapi.types.chat.CommonBot import dev.inmo.tgbotapi.types.chat.CommonUser import dev.inmo.tgbotapi.types.chat.ExtendedBot @@ -423,6 +424,8 @@ import dev.inmo.tgbotapi.types.request.UserShared import dev.inmo.tgbotapi.types.update.CallbackQueryUpdate import dev.inmo.tgbotapi.types.update.ChannelPostUpdate import dev.inmo.tgbotapi.types.update.ChatJoinRequestUpdate +import dev.inmo.tgbotapi.types.update.ChatMessageReactionUpdatedUpdate +import dev.inmo.tgbotapi.types.update.ChatMessageReactionsCountUpdatedUpdate import dev.inmo.tgbotapi.types.update.ChosenInlineResultUpdate import dev.inmo.tgbotapi.types.update.CommonChatMemberUpdatedUpdate import dev.inmo.tgbotapi.types.update.EditChannelPostUpdate @@ -2112,6 +2115,36 @@ public inline fun Chat.unknownChatTypeOrThrow(): UnknownChatType = this as public inline fun Chat.ifUnknownChatType(block: (UnknownChatType) -> T): T? = unknownChatTypeOrNull() ?.let(block) +public inline fun ChatMessageReactionUpdated.byChatOrNull(): ChatMessageReactionUpdated.ByChat? = + this as? dev.inmo.tgbotapi.types.chat.ChatMessageReactionUpdated.ByChat + +public inline fun ChatMessageReactionUpdated.byChatOrThrow(): ChatMessageReactionUpdated.ByChat = + this as dev.inmo.tgbotapi.types.chat.ChatMessageReactionUpdated.ByChat + +public inline fun + ChatMessageReactionUpdated.ifByChat(block: (ChatMessageReactionUpdated.ByChat) -> T): T? = + byChatOrNull() ?.let(block) + +public inline fun ChatMessageReactionUpdated.byUserOrNull(): ChatMessageReactionUpdated.ByUser? = + this as? dev.inmo.tgbotapi.types.chat.ChatMessageReactionUpdated.ByUser + +public inline fun ChatMessageReactionUpdated.byUserOrThrow(): ChatMessageReactionUpdated.ByUser = + this as dev.inmo.tgbotapi.types.chat.ChatMessageReactionUpdated.ByUser + +public inline fun + ChatMessageReactionUpdated.ifByUser(block: (ChatMessageReactionUpdated.ByUser) -> T): T? = + byUserOrNull() ?.let(block) + +public inline fun ChatMessageReactionUpdated.unknownOrNull(): ChatMessageReactionUpdated.Unknown? = + this as? dev.inmo.tgbotapi.types.chat.ChatMessageReactionUpdated.Unknown + +public inline fun ChatMessageReactionUpdated.unknownOrThrow(): ChatMessageReactionUpdated.Unknown = + this as dev.inmo.tgbotapi.types.chat.ChatMessageReactionUpdated.Unknown + +public inline fun + ChatMessageReactionUpdated.ifUnknown(block: (ChatMessageReactionUpdated.Unknown) -> T): T? = + unknownOrNull() ?.let(block) + public inline fun DiceAnimationType.cubeDiceAnimationTypeOrNull(): CubeDiceAnimationType? = this as? dev.inmo.tgbotapi.types.dice.CubeDiceAnimationType @@ -4567,6 +4600,28 @@ public inline fun Update.chatJoinRequestUpdateOrThrow(): ChatJoinRequestUpdate = public inline fun Update.ifChatJoinRequestUpdate(block: (ChatJoinRequestUpdate) -> T): T? = chatJoinRequestUpdateOrNull() ?.let(block) +public inline fun Update.chatMessageReactionUpdatedUpdateOrNull(): ChatMessageReactionUpdatedUpdate? + = this as? dev.inmo.tgbotapi.types.update.ChatMessageReactionUpdatedUpdate + +public inline fun Update.chatMessageReactionUpdatedUpdateOrThrow(): ChatMessageReactionUpdatedUpdate + = this as dev.inmo.tgbotapi.types.update.ChatMessageReactionUpdatedUpdate + +public inline fun + Update.ifChatMessageReactionUpdatedUpdate(block: (ChatMessageReactionUpdatedUpdate) -> T): T? = + chatMessageReactionUpdatedUpdateOrNull() ?.let(block) + +public inline fun Update.chatMessageReactionsCountUpdatedUpdateOrNull(): + ChatMessageReactionsCountUpdatedUpdate? = this as? + dev.inmo.tgbotapi.types.update.ChatMessageReactionsCountUpdatedUpdate + +public inline fun Update.chatMessageReactionsCountUpdatedUpdateOrThrow(): + ChatMessageReactionsCountUpdatedUpdate = this as + dev.inmo.tgbotapi.types.update.ChatMessageReactionsCountUpdatedUpdate + +public inline fun + Update.ifChatMessageReactionsCountUpdatedUpdate(block: (ChatMessageReactionsCountUpdatedUpdate) -> T): + T? = chatMessageReactionsCountUpdatedUpdateOrNull() ?.let(block) + public inline fun Update.chosenInlineResultUpdateOrNull(): ChosenInlineResultUpdate? = this as? dev.inmo.tgbotapi.types.update.ChosenInlineResultUpdate diff --git a/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/extensions/UpdateChatRetriever.kt b/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/extensions/UpdateChatRetriever.kt index b3de4b565f..c92600b96a 100644 --- a/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/extensions/UpdateChatRetriever.kt +++ b/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/extensions/UpdateChatRetriever.kt @@ -40,6 +40,8 @@ fun Update.sourceChatWithConverters( editChannelPostUpdateConverter: (EditChannelPostUpdate) -> Chat? = { it.data.chat }, editMessageUpdateConverter: (EditMessageUpdate) -> Chat? = { it.data.chat }, myChatMemberUpdatedUpdateConverter: (MyChatMemberUpdatedUpdate) -> Chat? = { it.data.chat }, + chatMessageReactionUpdatedUpdateConverter: (ChatMessageReactionUpdatedUpdate) -> Chat? = { it.data.chat }, + chatMessageReactionsCountUpdatedUpdateConverter: (ChatMessageReactionsCountUpdatedUpdate) -> Chat? = { it.data.chat }, commonChatMemberUpdatedUpdateConverter: (CommonChatMemberUpdatedUpdate) -> Chat? = { it.data.chat } ): Chat? = when (this) { is BaseMessageUpdate -> baseMessageUpdateConverter(this) @@ -57,6 +59,8 @@ fun Update.sourceChatWithConverters( is EditMessageUpdate -> editMessageUpdateConverter(this) is MyChatMemberUpdatedUpdate -> myChatMemberUpdatedUpdateConverter(this) is CommonChatMemberUpdatedUpdate -> commonChatMemberUpdatedUpdateConverter(this) + is ChatMessageReactionUpdatedUpdate -> chatMessageReactionUpdatedUpdateConverter(this) + is ChatMessageReactionsCountUpdatedUpdate -> chatMessageReactionsCountUpdatedUpdateConverter(this) else -> { when (val data = data) { is FromUser -> data.from