From c96e162845ba755dbb5e06c69a9d8169fb639f8a Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 18 Aug 2023 23:05:43 +0600 Subject: [PATCH 01/12] start 9.1.0 --- CHANGELOG.md | 2 ++ gradle.properties | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b42fcc03cc..8064e0223f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # TelegramBotAPI changelog +## 9.1.0 + ## 9.0.0 **THIS UPDATE CONTAINS BREAKING CHANGES: USERNAMES OF BOTS NOW BECAME NULLABLE** diff --git a/gradle.properties b/gradle.properties index 923f424c4e..48a5330d31 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,4 +6,4 @@ kotlin.incremental=true kotlin.incremental.js=true library_group=dev.inmo -library_version=9.0.0 +library_version=9.1.0 From b575871a8ead6b11aeaa28b9f7bb270a8e44aa4f Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 18 Aug 2023 23:13:56 +0600 Subject: [PATCH 02/12] update dependencies --- CHANGELOG.md | 5 +++++ gradle/libs.versions.toml | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8064e0223f..bc5c01c6d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## 9.1.0 +* `Version`: + * `Coroutines`: `1.7.2` -> `1.7.3` + * `Ktor`: `2.3.2` -> `2.3.3` + * `MicroUtils`: `0.19.7` -> `0.19.9` + ## 9.0.0 **THIS UPDATE CONTAINS BREAKING CHANGES: USERNAMES OF BOTS NOW BECAME NULLABLE** diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7808783a44..202011f887 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,18 +2,18 @@ kotlin = "1.8.22" kotlin-serialization = "1.5.1" -kotlin-coroutines = "1.7.2" +kotlin-coroutines = "1.7.3" javax-activation = "1.1.1" korlibs = "4.0.3" uuid = "0.7.1" -ktor = "2.3.2" +ktor = "2.3.3" ksp = "1.8.22-1.0.11" kotlin-poet = "1.14.2" -microutils = "0.19.7" +microutils = "0.19.9" github-release-plugin = "2.4.1" dokka = "1.8.20" From 085a225eb4e0e8b65cd65f28ffe2975c5f20aeeb Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 18 Aug 2023 23:27:15 +0600 Subject: [PATCH 03/12] add support of voter_chat in PollAnswer --- .../kotlin/dev/inmo/tgbotapi/types/Common.kt | 1 + .../inmo/tgbotapi/types/polls/PollAnswer.kt | 90 +++++++++++++++++-- 2 files changed, 84 insertions(+), 7 deletions(-) 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 95023b91a9..29100932c6 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 @@ -289,6 +289,7 @@ const val pinnedMessageField = "pinned_message" const val activeUsernamesField = "active_usernames" const val customTitleField = "custom_title" const val optionIdsField = "option_ids" +const val voterChatField = "voter_chat" const val ipAddressField = "ip_address" const val linkedChatIdField = "linked_chat_id" const val hasHiddenMembersField = "has_hidden_members" diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/PollAnswer.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/PollAnswer.kt index 6b46f43124..d98231241b 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/PollAnswer.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/PollAnswer.kt @@ -2,19 +2,95 @@ package dev.inmo.tgbotapi.types.polls import dev.inmo.tgbotapi.abstracts.FromUser import dev.inmo.tgbotapi.types.* +import dev.inmo.tgbotapi.types.chat.ChannelChat +import dev.inmo.tgbotapi.types.chat.CommonBot import dev.inmo.tgbotapi.types.chat.User import kotlinx.serialization.* +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder @Serializable -data class PollAnswer( - @SerialName(pollIdField) - val pollId: PollIdentifier, - @SerialName(userField) - override val user: User, - @SerialName(optionIdsField) +sealed interface PollAnswer: FromUser { + val pollId: PollIdentifier + override val user: User val chosen: List -) : FromUser { @Transient override val from: User get() = user + + @Serializable + data class Common( + @SerialName(pollIdField) + override val pollId: PollIdentifier, + @SerialName(userField) + override val user: User, + @SerialName(optionIdsField) + override val chosen: List, + ) : PollAnswer + + @Serializable + data class InChannel( + @SerialName(pollIdField) + override val pollId: PollIdentifier, + @SerialName(voterChatField) + val voterChat: ChannelChat, + @SerialName(optionIdsField) + override val chosen: List + ) : PollAnswer { + @SerialName(userField) + override val user: User = defaultUser + + companion object { + val defaultUser = CommonBot( + UserId(136817688L), + "", + "", + Username("@Channel_Bot") + ) + } + } + + companion object : KSerializer { + @Serializable + private data class PollAnswerSurrogate( + @SerialName(pollIdField) + val pollId: PollIdentifier, + @SerialName(userField) + val user: User, + @SerialName(optionIdsField) + val chosen: List, + @SerialName(voterChatField) + val voterChat: ChannelChat? + ) + operator fun invoke( + pollId: PollIdentifier, + user: User, + chosen: List, + ) = Common(pollId, user, chosen) + + override val descriptor: SerialDescriptor + get() = PollAnswerSurrogate.serializer().descriptor + + override fun deserialize(decoder: Decoder): PollAnswer { + val surrogate = PollAnswerSurrogate.serializer().deserialize(decoder) + return if (surrogate.voterChat != null) { + InChannel(surrogate.pollId, surrogate.voterChat, surrogate.chosen) + } else { + Common(surrogate.pollId, surrogate.user, surrogate.chosen) + } + } + + override fun serialize(encoder: Encoder, value: PollAnswer) { + PollAnswerSurrogate.serializer().serialize( + encoder, + PollAnswerSurrogate( + value.pollId, + value.user, + value.chosen, + (value as? InChannel) ?.voterChat + ) + ) + } + } } From 0840d2e083717c2b1f09ba958c3b0ba3b5e5e6c4 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 18 Aug 2023 23:31:30 +0600 Subject: [PATCH 04/12] add emoji_status_expiration_date support in Chat --- .../src/commonMain/kotlin/dev/inmo/tgbotapi/types/Common.kt | 1 + .../kotlin/dev/inmo/tgbotapi/types/chat/Extended.kt | 5 ++++- .../kotlin/dev/inmo/tgbotapi/types/chat/ExtendedAbstracts.kt | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) 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 29100932c6..4764f8d400 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 @@ -214,6 +214,7 @@ const val isPremiumField = "is_premium" const val hasPrivateForwardsField = "has_private_forwards" const val hasRestrictedVoiceAndVideoMessagesField = "has_restricted_voice_and_video_messages" const val emojiStatusCustomEmojiIdField = "emoji_status_custom_emoji_id" +const val emojiStatusExpirationDateField = "emoji_status_expiration_date" const val iconCustomEmojiIdField = "icon_custom_emoji_id" const val canJoinGroupsField = "can_join_groups" const val canReadAllGroupMessagesField = "can_read_all_group_messages" diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/Extended.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/Extended.kt index 5dbadf9633..1cc41715e5 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/Extended.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/Extended.kt @@ -4,6 +4,7 @@ import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.message.abstracts.Message import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializeOnlySerializer import dev.inmo.tgbotapi.utils.RiskFeature +import korlibs.time.DateTime import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.json.JsonObject @@ -78,7 +79,9 @@ data class ExtendedPrivateChatImpl( @SerialName(hasRestrictedVoiceAndVideoMessagesField) override val hasRestrictedVoiceAndVideoMessages: Boolean = false, @SerialName(emojiStatusCustomEmojiIdField) - override val statusEmojiId: CustomEmojiId? = null + override val statusEmojiId: CustomEmojiId? = null, + @SerialName(emojiStatusExpirationDateField) + override val statusEmojiExpiration: TelegramDate? = null ) : ExtendedPrivateChat typealias ExtendedUser = ExtendedPrivateChatImpl diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/ExtendedAbstracts.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/ExtendedAbstracts.kt index 9d2bc0bcbe..09ac9d6f4f 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/ExtendedAbstracts.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/ExtendedAbstracts.kt @@ -3,6 +3,7 @@ package dev.inmo.tgbotapi.types.chat import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.message.abstracts.Message import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializeOnlySerializer +import korlibs.time.DateTime import kotlinx.serialization.Serializable @Serializable(ExtendedChatSerializer.Companion::class) @@ -21,6 +22,7 @@ sealed interface ExtendedPrivateChat : PrivateChat, ExtendedChatWithUsername { val hasPrivateForwards: Boolean val hasRestrictedVoiceAndVideoMessages: Boolean val statusEmojiId: CustomEmojiId? + val statusEmojiExpiration: TelegramDate? val allowCreateUserIdLink: Boolean get() = hasPrivateForwards From 4b5baaff8ca45f78ca326416a67c02b921797193 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 18 Aug 2023 23:34:44 +0600 Subject: [PATCH 05/12] add suport of unpinAllGeneralForumTopicMessages --- .../UnpinAllGeneralForumTopicMessages.kt | 21 +++++++++++++++++++ .../UnpinAllGeneralForumTopicMessages.kt | 14 +++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/chat/forum/UnpinAllGeneralForumTopicMessages.kt create mode 100644 tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/chat/forum/UnpinAllGeneralForumTopicMessages.kt diff --git a/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/chat/forum/UnpinAllGeneralForumTopicMessages.kt b/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/chat/forum/UnpinAllGeneralForumTopicMessages.kt new file mode 100644 index 0000000000..39afb4b290 --- /dev/null +++ b/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/chat/forum/UnpinAllGeneralForumTopicMessages.kt @@ -0,0 +1,21 @@ +package dev.inmo.tgbotapi.extensions.api.chat.forum + +import dev.inmo.tgbotapi.bot.TelegramBot +import dev.inmo.tgbotapi.requests.chat.forum.UnpinAllForumTopicMessages +import dev.inmo.tgbotapi.requests.chat.forum.UnpinAllGeneralForumTopicMessages +import dev.inmo.tgbotapi.types.ChatIdentifier +import dev.inmo.tgbotapi.types.ForumTopic +import dev.inmo.tgbotapi.types.MessageThreadId +import dev.inmo.tgbotapi.types.chat.Chat + +suspend fun TelegramBot.unpinAllGeneralForumTopicMessages( + chatId: ChatIdentifier +) = execute( + UnpinAllGeneralForumTopicMessages( + chatId + ) +) + +suspend fun TelegramBot.unpinAllGeneralForumTopicMessages( + chat: Chat +) = unpinAllGeneralForumTopicMessages(chat.id) diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/chat/forum/UnpinAllGeneralForumTopicMessages.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/chat/forum/UnpinAllGeneralForumTopicMessages.kt new file mode 100644 index 0000000000..777a75796c --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/chat/forum/UnpinAllGeneralForumTopicMessages.kt @@ -0,0 +1,14 @@ +package dev.inmo.tgbotapi.requests.chat.forum + +import dev.inmo.tgbotapi.types.* +import kotlinx.serialization.* + +@Serializable +data class UnpinAllGeneralForumTopicMessages ( + @SerialName(chatIdField) + override val chatId: ChatIdentifier, +): ModifyForumRequest { + override fun method(): String = "unpinAllGeneralForumTopicMessages" + override val requestSerializer: SerializationStrategy<*> + get() = serializer() +} From a65971be00422bc3e2935841b3468e0fdcf2ae5c Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sat, 19 Aug 2023 00:31:36 +0600 Subject: [PATCH 06/12] start add stories --- .../inmo/tgbotapi/types/message/RawMessage.kt | 7 ++++ .../types/message/content/StoryContent.kt | 38 +++++++++++++++++++ .../dev/inmo/tgbotapi/types/stories/Story.kt | 6 +++ 3 files changed, 51 insertions(+) create mode 100644 tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/StoryContent.kt create mode 100644 tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/stories/Story.kt 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 eb43475213..6a5d7f2c6a 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 @@ -31,6 +31,7 @@ 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.stories.Story import dev.inmo.tgbotapi.types.venue.Venue import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -65,6 +66,7 @@ internal data class RawMessage( private val caption: String? = null, private val caption_entities: RawMessageEntities? = null, private val has_media_spoiler: Boolean? = null, + private val story: Story? = null, private val audio: AudioFile? = null, private val document: DocumentFile? = null, private val animation: AnimationFile? = null, @@ -134,6 +136,11 @@ internal data class RawMessage( } ?: emptyList() when { + story != null -> StoryContent( + from ?: error("For story content field 'from' is required and should contains User info"), + messageId, + story + ) text != null -> TextContent(text, (entities ?: emptyList()).asTextSources(text)) audio != null -> AudioContent( audio, diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/StoryContent.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/StoryContent.kt new file mode 100644 index 0000000000..201de4cbec --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/StoryContent.kt @@ -0,0 +1,38 @@ +package dev.inmo.tgbotapi.types.message.content + +import dev.inmo.tgbotapi.requests.ForwardMessage +import dev.inmo.tgbotapi.requests.abstracts.Request +import dev.inmo.tgbotapi.types.ChatIdentifier +import dev.inmo.tgbotapi.types.MessageId +import dev.inmo.tgbotapi.types.MessageThreadId +import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup +import dev.inmo.tgbotapi.types.chat.Chat +import dev.inmo.tgbotapi.types.message.abstracts.Message +import dev.inmo.tgbotapi.types.stories.Story +import kotlinx.serialization.Serializable + +@Serializable +data class StoryContent( + private val from: Chat, + private val messageId: MessageId, + val story: Story +) : MessageContent { + override fun createResend( + chatId: ChatIdentifier, + messageThreadId: MessageThreadId?, + disableNotification: Boolean, + protectContent: Boolean, + replyToMessageId: MessageId?, + allowSendingWithoutReply: Boolean?, + replyMarkup: KeyboardMarkup? + ): Request { + return ForwardMessage( + from.id, + toChatId = chatId, + messageId = messageId, + threadId = messageThreadId, + disableNotification = disableNotification, + protectContent = protectContent + ) + } +} diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/stories/Story.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/stories/Story.kt new file mode 100644 index 0000000000..592188a196 --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/stories/Story.kt @@ -0,0 +1,6 @@ +package dev.inmo.tgbotapi.types.stories + +import kotlinx.serialization.Serializable + +@Serializable +class Story From 6873c23309da6c9d268b864c5bfe4994c639f4db Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sat, 19 Aug 2023 16:41:08 +0600 Subject: [PATCH 07/12] complete story support --- .../expectations/WaitContent.kt | 4 ++++ .../expectations/WaitContentMessage.kt | 4 ++++ .../triggers_handling/ContentTriggers.kt | 24 +++++++++++++++++++ .../types/message/content/Typealiases.kt | 1 + .../extensions/utils/ClassCastsNew.kt | 10 ++++++++ .../utils/ContentMessageConversations.kt | 1 + .../utils/shortcuts/FlowsUpdatesFilter.kt | 5 ++++ 7 files changed, 49 insertions(+) diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitContent.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitContent.kt index fa854b6c77..6bafc17182 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitContent.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitContent.kt @@ -62,6 +62,10 @@ suspend fun BehaviourContext.waitText( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } ) = waitContent(initRequest, errorFactory).mapContent() +suspend fun BehaviourContext.waitStory( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null } +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitVenue( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitContentMessage.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitContentMessage.kt index 99b8c27a76..d0e151480a 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitContentMessage.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitContentMessage.kt @@ -74,6 +74,10 @@ suspend fun BehaviourContext.waitTextMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } ) = waitContentMessage(initRequest, errorFactory).mapWithContent() +suspend fun BehaviourContext.waitStoryMessage( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null } +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitVenueMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ContentTriggers.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ContentTriggers.kt index 80901c26bf..a2b1a002b4 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ContentTriggers.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ContentTriggers.kt @@ -248,6 +248,30 @@ suspend fun BC.onText( 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.onStory( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver? = MessageFilterByChat, + markerFactory: MarkerFactory = ByChatMessageMarkerFactory, + scenarioReceiver: CustomBehaviourContextAndTypeReceiver +) = onContentMessageWithType( + 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, diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/Typealiases.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/Typealiases.kt index 7cd305fdff..9e9a865f9f 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/Typealiases.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/Typealiases.kt @@ -11,6 +11,7 @@ typealias DiceMessage = CommonMessage typealias ContactMessage = CommonMessage typealias PollMessage = CommonMessage typealias TextMessage = CommonMessage +typealias StoryMessage = CommonMessage typealias LocationMessage = CommonMessage typealias LiveLocationMessage = CommonMessage 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 d8cd7d52f4..e0fcb89557 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 @@ -292,6 +292,7 @@ import dev.inmo.tgbotapi.types.message.content.ResendableContent import dev.inmo.tgbotapi.types.message.content.SpoilerableMediaContent import dev.inmo.tgbotapi.types.message.content.StaticLocationContent import dev.inmo.tgbotapi.types.message.content.StickerContent +import dev.inmo.tgbotapi.types.message.content.StoryContent import dev.inmo.tgbotapi.types.message.content.TextContent import dev.inmo.tgbotapi.types.message.content.TextedContent import dev.inmo.tgbotapi.types.message.content.TextedMediaContent @@ -3480,6 +3481,15 @@ public inline fun ResendableContent.stickerContentOrThrow(): StickerContent = th public inline fun ResendableContent.ifStickerContent(block: (StickerContent) -> T): T? = stickerContentOrNull() ?.let(block) +public inline fun ResendableContent.storyContentOrNull(): StoryContent? = this as? + dev.inmo.tgbotapi.types.message.content.StoryContent + +public inline fun ResendableContent.storyContentOrThrow(): StoryContent = this as + dev.inmo.tgbotapi.types.message.content.StoryContent + +public inline fun ResendableContent.ifStoryContent(block: (StoryContent) -> T): T? = + storyContentOrNull() ?.let(block) + public inline fun ResendableContent.textContentOrNull(): TextContent? = this as? dev.inmo.tgbotapi.types.message.content.TextContent diff --git a/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ContentMessageConversations.kt b/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ContentMessageConversations.kt index e9b370dc5a..5366e98fe7 100644 --- a/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ContentMessageConversations.kt +++ b/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ContentMessageConversations.kt @@ -21,6 +21,7 @@ fun Flow>.onlyPhotoContentMessages() = withContentType>.onlyPollContentMessages() = withContentType() fun Flow>.onlyStickerContentMessages() = withContentType() fun Flow>.onlyTextContentMessages() = withContentType() +fun Flow>.onlyStoryContentMessages() = withContentType() fun Flow>.onlyVenueContentMessages() = withContentType() fun Flow>.onlyVideoContentMessages() = withContentType() fun Flow>.onlyVideoNoteContentMessages() = withContentType() diff --git a/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/shortcuts/FlowsUpdatesFilter.kt b/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/shortcuts/FlowsUpdatesFilter.kt index 91acd5419e..566db560a6 100644 --- a/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/shortcuts/FlowsUpdatesFilter.kt +++ b/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/shortcuts/FlowsUpdatesFilter.kt @@ -120,6 +120,11 @@ fun FlowsUpdatesFilter.textMessages( scopeToIncludeChannels: CoroutineScope? = null ) = filterContentMessages(scopeToIncludeChannels) +fun Flow.storyMessages() = filterContentMessages() +fun FlowsUpdatesFilter.storyMessages( + scopeToIncludeChannels: CoroutineScope? = null +) = filterContentMessages(scopeToIncludeChannels) + fun Flow.venueMessages() = filterContentMessages() fun FlowsUpdatesFilter.venueMessages( scopeToIncludeChannels: CoroutineScope? = null From 051f5e22e76524e1263bccb10dc2edda7d297129 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sat, 19 Aug 2023 18:15:54 +0600 Subject: [PATCH 08/12] fix of createResend in story content --- .../kotlin/dev/inmo/tgbotapi/types/message/RawMessage.kt | 2 +- .../dev/inmo/tgbotapi/types/message/content/StoryContent.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) 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 6a5d7f2c6a..2a4feb665b 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 @@ -137,7 +137,7 @@ internal data class RawMessage( when { story != null -> StoryContent( - from ?: error("For story content field 'from' is required and should contains User info"), + chat, messageId, story ) diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/StoryContent.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/StoryContent.kt index 201de4cbec..48e85ade62 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/StoryContent.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/StoryContent.kt @@ -13,7 +13,7 @@ import kotlinx.serialization.Serializable @Serializable data class StoryContent( - private val from: Chat, + private val chat: Chat, private val messageId: MessageId, val story: Story ) : MessageContent { @@ -27,7 +27,7 @@ data class StoryContent( replyMarkup: KeyboardMarkup? ): Request { return ForwardMessage( - from.id, + chat.id, toChatId = chatId, messageId = messageId, threadId = messageThreadId, From 1e451af50807a17204bd91d716f18f1bc9559a81 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sat, 19 Aug 2023 18:40:12 +0600 Subject: [PATCH 09/12] update telegram bot api support info --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4ac3a9b6ca..bd4732d6fe 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# TelegramBotAPI [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi) [![Supported version](https://img.shields.io/badge/Telegram%20Bot%20API-6.7-blue)](https://core.telegram.org/bots/api-changelog#april-21-2023) +# TelegramBotAPI [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi) [![Supported version](https://img.shields.io/badge/Telegram%20Bot%20API-6.8-blue)](https://core.telegram.org/bots/api-changelog#august-18-2023) | Docs | [![KDocs](https://img.shields.io/static/v1?label=Dokka&message=KDocs&color=blue&logo=kotlin)](https://tgbotapi.inmo.dev/index.html) [![Mini tutorial](https://img.shields.io/static/v1?label=Mk&message=Docs&color=blue&logo=mkdocs)](https://docs.inmo.dev/tgbotapi/index.html) | |:----------------------:|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:| From 117d891ff2f945f37c69742e43b3aaa81e3056b0 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sat, 19 Aug 2023 23:55:59 +0600 Subject: [PATCH 10/12] update changelog and PollAnswer --- CHANGELOG.md | 2 ++ .../kotlin/dev/inmo/tgbotapi/types/polls/PollAnswer.kt | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc5c01c6d0..288b73f7b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## 9.1.0 +**This update contains adding of [Telegram Bot API 6.8](https://core.telegram.org/bots/api-changelog#august-18-2023) support** + * `Version`: * `Coroutines`: `1.7.2` -> `1.7.3` * `Ktor`: `2.3.2` -> `2.3.3` diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/PollAnswer.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/PollAnswer.kt index d98231241b..d33b180be6 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/PollAnswer.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/PollAnswer.kt @@ -10,7 +10,7 @@ import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder -@Serializable +@Serializable(PollAnswer.Companion::class) sealed interface PollAnswer: FromUser { val pollId: PollIdentifier override val user: User From d59e20400236a3a0f3ead013453a841d39a3a11c Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sun, 20 Aug 2023 00:27:33 +0600 Subject: [PATCH 11/12] rename PollAnswer inheritors --- .../dev/inmo/tgbotapi/types/polls/PollAnswer.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/PollAnswer.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/PollAnswer.kt index d33b180be6..9242251a49 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/PollAnswer.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/PollAnswer.kt @@ -20,7 +20,7 @@ sealed interface PollAnswer: FromUser { get() = user @Serializable - data class Common( + data class Public( @SerialName(pollIdField) override val pollId: PollIdentifier, @SerialName(userField) @@ -30,7 +30,7 @@ sealed interface PollAnswer: FromUser { ) : PollAnswer @Serializable - data class InChannel( + data class Anonymous( @SerialName(pollIdField) override val pollId: PollIdentifier, @SerialName(voterChatField) @@ -67,7 +67,7 @@ sealed interface PollAnswer: FromUser { pollId: PollIdentifier, user: User, chosen: List, - ) = Common(pollId, user, chosen) + ) = Public(pollId, user, chosen) override val descriptor: SerialDescriptor get() = PollAnswerSurrogate.serializer().descriptor @@ -75,9 +75,9 @@ sealed interface PollAnswer: FromUser { override fun deserialize(decoder: Decoder): PollAnswer { val surrogate = PollAnswerSurrogate.serializer().deserialize(decoder) return if (surrogate.voterChat != null) { - InChannel(surrogate.pollId, surrogate.voterChat, surrogate.chosen) + Anonymous(surrogate.pollId, surrogate.voterChat, surrogate.chosen) } else { - Common(surrogate.pollId, surrogate.user, surrogate.chosen) + Public(surrogate.pollId, surrogate.user, surrogate.chosen) } } @@ -88,7 +88,7 @@ sealed interface PollAnswer: FromUser { value.pollId, value.user, value.chosen, - (value as? InChannel) ?.voterChat + (value as? Anonymous) ?.voterChat ) ) } From c260597799667a10b8c82e9a314d91a29880fba2 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sun, 20 Aug 2023 02:30:36 +0600 Subject: [PATCH 12/12] fixes in poll answer --- .../kotlin/dev/inmo/tgbotapi/types/polls/PollAnswer.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/PollAnswer.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/PollAnswer.kt index 9242251a49..644196389e 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/PollAnswer.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/polls/PollAnswer.kt @@ -56,12 +56,12 @@ sealed interface PollAnswer: FromUser { private data class PollAnswerSurrogate( @SerialName(pollIdField) val pollId: PollIdentifier, - @SerialName(userField) - val user: User, @SerialName(optionIdsField) val chosen: List, + @SerialName(userField) + val user: User = Anonymous.defaultUser, @SerialName(voterChatField) - val voterChat: ChannelChat? + val voterChat: ChannelChat? = null ) operator fun invoke( pollId: PollIdentifier, @@ -86,8 +86,8 @@ sealed interface PollAnswer: FromUser { encoder, PollAnswerSurrogate( value.pollId, - value.user, value.chosen, + value.user, (value as? Anonymous) ?.voterChat ) )