From 191fa5406d5fb9cd4eb9cd68fa33828a58857b34 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 11 May 2023 20:45:24 +0600 Subject: [PATCH 1/6] start 7.1.3 --- CHANGELOG.md | 2 ++ gradle.properties | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e76cd51097..f2b73ac97a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # TelegramBotAPI changelog +## 7.1.3 + ## 7.1.2 * `Versions`: diff --git a/gradle.properties b/gradle.properties index 187a1d1c57..414883468b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,4 +6,4 @@ kotlin.incremental=true kotlin.incremental.js=true library_group=dev.inmo -library_version=7.1.2 +library_version=7.1.3 From 1a21fa85ac58c4484e760c0db66a29e509a6503f Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 18 May 2023 11:39:47 +0600 Subject: [PATCH 2/6] fixes --- CHANGELOG.md | 4 ++++ gradle/libs.versions.toml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2b73ac97a..aeabbc506d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## 7.1.3 +* `Versions`: + * `Serialization`: `1.5.0` -> `1.5.1` + * `MicroUtils`: `0.18.1` -> `0.18.4` + ## 7.1.2 * `Versions`: diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 26c68c0fcc..c3447eda98 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] kotlin = "1.8.21" -kotlin-serialization = "1.5.0" +kotlin-serialization = "1.5.1" kotlin-coroutines = "1.6.4" javax-activation = "1.1.1" @@ -13,7 +13,7 @@ ktor = "2.3.0" ksp = "1.8.21-1.0.11" kotlin-poet = "1.13.2" -microutils = "0.18.1" +microutils = "0.18.4" github-release-plugin = "2.4.1" dokka = "1.8.10" From cb4c48d025525801a5c8cc7a68edc65bae02bbed Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 18 May 2023 11:45:27 +0600 Subject: [PATCH 3/6] waitMediaContent/waitMediaContentMessage/onMediaContent --- CHANGELOG.md | 6 +++-- .../expectations/WaitContent.kt | 4 ++++ .../expectations/WaitContentMessage.kt | 5 ++++ .../triggers_handling/ContentTriggers.kt | 24 +++++++++++++++++++ 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aeabbc506d..4277400247 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,10 @@ ## 7.1.3 * `Versions`: - * `Serialization`: `1.5.0` -> `1.5.1` - * `MicroUtils`: `0.18.1` -> `0.18.4` + * `Serialization`: `1.5.0` -> `1.5.1` + * `MicroUtils`: `0.18.1` -> `0.18.4` +* `BehaviourBuilder`: + * Now it is possible to use `waitMediaContent`/`waitMediaContentMessage`/`onMediaContent` ## 7.1.2 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 007ff4d2cd..a2594d9ad8 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 @@ -124,3 +124,7 @@ suspend fun BehaviourContext.waitVisualContent( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } ) = waitContent(initRequest, errorFactory) +suspend fun BehaviourContext.waitMediaContent( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null } +) = waitContent(initRequest, errorFactory) 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 e79ae00a13..f339620627 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 @@ -151,3 +151,8 @@ suspend fun BehaviourContext.waitVisualContentMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } ) = waitContentMessage(initRequest, errorFactory) + +suspend fun BehaviourContext.waitMediaContentMessage( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null } +) = waitContentMessage(initRequest, errorFactory) 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 e070df87f3..e6ce8d8a3c 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 @@ -631,3 +631,27 @@ suspend fun BC.onVisualContent( 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.onMediaContent( + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver = MessageFilterByChat, + markerFactory: MarkerFactory = ByChatMessageMarkerFactory, + scenarioReceiver: CustomBehaviourContextAndTypeReceiver +) = onContentMessageWithType( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) From ed2c447730ddb3f093de77156f3ca836b3e0d403 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 18 May 2023 12:59:35 +0600 Subject: [PATCH 4/6] fix of #645 --- CHANGELOG.md | 2 + .../expectations/WaitContent.kt | 64 ++-- .../expectations/WaitContentMessage.kt | 84 ++--- .../expectations/WaitMention.kt | 107 ++++++ .../expectations/WaitMentionMessage.kt | 82 ++++ .../triggers_handling/ContentTriggers.kt | 24 ++ .../triggers_handling/MentionTriggers.kt | 357 ++++++++++++++++++ .../types/message/content/Abstracts.kt | 18 + .../types/message/content/AbstractsMedia.kt | 2 +- .../types/message/content/TextContent.kt | 2 +- .../types/message/content/Typealiases.kt | 2 + 11 files changed, 667 insertions(+), 77 deletions(-) create mode 100644 tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitMention.kt create mode 100644 tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitMentionMessage.kt create mode 100644 tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/MentionTriggers.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 4277400247..747aa60508 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ * `MicroUtils`: `0.18.1` -> `0.18.4` * `BehaviourBuilder`: * Now it is possible to use `waitMediaContent`/`waitMediaContentMessage`/`onMediaContent` + * Add `onMention`/`waitMention` functionality + * Add opportunity to map content with extensions to `Flow` ## 7.1.2 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 a2594d9ad8..fa854b6c77 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 @@ -10,121 +10,127 @@ import dev.inmo.tgbotapi.utils.RiskFeature import dev.inmo.tgbotapi.utils.lowLevelRiskFeatureMessage import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.mapNotNull typealias CommonMessageToContentMapper = suspend CommonMessage.() -> T? @RiskFeature(lowLevelRiskFeatureMessage) -suspend inline fun BehaviourContext.waitContent( +suspend inline fun BehaviourContext.waitContent( initRequest: Request<*>? = null, noinline errorFactory: NullableRequestBuilder<*> = { null } -): Flow = waitContentMessage(initRequest, errorFactory).map { it.content } +): Flow = waitContentMessage(initRequest, errorFactory).map { it.content } +inline fun Flow.mapContent() = mapNotNull { it as? T } suspend fun BehaviourContext.waitAnyContent( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory) +suspend fun BehaviourContext.waitTextedContent( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null } +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitContact( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitDice( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitGame( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitLocation( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitLiveLocation( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitStaticLocation( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitPoll( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitText( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitVenue( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitAudioMediaGroupContent( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null }, -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitDocumentMediaGroupContent( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitMedia( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitAnyMediaGroupContent( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null }, -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitVisualMediaGroupContent( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null }, -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitTextedMediaContent( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null }, -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitAnimation( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitAudio( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null }, -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitDocument( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null }, -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitPhoto( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null }, -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitSticker( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitVideo( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitVideoNote( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitVoice( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitInvoice( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitVisualContent( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() suspend fun BehaviourContext.waitMediaContent( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContent(initRequest, errorFactory) +) = waitContent(initRequest, errorFactory).mapContent() 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 f339620627..99b8c27a76 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 @@ -5,6 +5,7 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations import dev.inmo.micro_utils.coroutines.safelyWithoutExceptions import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext import dev.inmo.tgbotapi.extensions.utils.withContent +import dev.inmo.tgbotapi.extensions.utils.withContentOrNull import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage import dev.inmo.tgbotapi.types.message.content.* @@ -12,147 +13,138 @@ import dev.inmo.tgbotapi.types.update.abstracts.BaseSentMessageUpdate import dev.inmo.tgbotapi.utils.RiskFeature import dev.inmo.tgbotapi.utils.lowLevelRiskFeatureMessage import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.mapNotNull typealias CommonMessageToCommonMessageMapper = suspend CommonMessage.() -> CommonMessage? @RiskFeature(lowLevelRiskFeatureMessage) -suspend inline fun BehaviourContext.waitContentMessage( +suspend inline fun BehaviourContext.waitContentMessage( initRequest: Request<*>? = null, noinline errorFactory: NullableRequestBuilder<*> = { null } -): Flow> = expectFlow( +): Flow> = expectFlow( initRequest, errorFactory ) { if (it !is BaseSentMessageUpdate) { return@expectFlow emptyList() } - listOfNotNull((it.data as? CommonMessage<*>) ?.withContent()) + listOfNotNull((it.data as? CommonMessage<*>)) } -internal inline fun contentMessageConverter( - noinline mapper: CommonMessageToCommonMessageMapper? = null -): suspend CommonMessage.() -> CommonMessage? = mapper ?.let { - { - if (content is T) { - @Suppress("UNCHECKED_CAST") - val message = (this as CommonMessage) - safelyWithoutExceptions { mapper(message) } - } else { - null - } - } -} ?: { - @Suppress("UNCHECKED_CAST") - if (content is T) this as CommonMessage else null -} +inline fun Flow>.mapWithContent() = mapNotNull { it.withContentOrNull() } suspend fun BehaviourContext.waitAnyContentMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null }, -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory) +suspend fun BehaviourContext.waitTextedContentMessage( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitContactMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitDiceMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitGameMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitLocationMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitLiveLocationMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitStaticLocationMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitPollMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitTextMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitVenueMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitAudioMediaGroupContentMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitDocumentMediaGroupContentMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitMediaMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitAnyMediaGroupContentMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitVisualMediaGroupContentMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitTextedMediaContentMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitAnimationMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitAudioMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitDocumentMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitPhotoMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitStickerMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitVideoMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitVideoNoteMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitVoiceMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitInvoiceMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitVisualContentMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() suspend fun BehaviourContext.waitMediaContentMessage( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null } -) = waitContentMessage(initRequest, errorFactory) +) = waitContentMessage(initRequest, errorFactory).mapWithContent() diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitMention.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitMention.kt new file mode 100644 index 0000000000..817251f08b --- /dev/null +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitMention.kt @@ -0,0 +1,107 @@ +package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations + +import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext +import dev.inmo.tgbotapi.extensions.utils.whenMentionTextSource +import dev.inmo.tgbotapi.extensions.utils.whenTextMentionTextSource +import dev.inmo.tgbotapi.requests.abstracts.Request +import dev.inmo.tgbotapi.types.UserId +import dev.inmo.tgbotapi.types.Username +import dev.inmo.tgbotapi.types.chat.User +import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage +import dev.inmo.tgbotapi.types.message.content.MessageContent +import dev.inmo.tgbotapi.types.message.content.TextedContent +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.filter + +/** + * Check, that [TextedContent.textSources] contains: + * + * * Any [dev.inmo.tgbotapi.types.message.textsources.MentionTextSource] with [dev.inmo.tgbotapi.types.message.textsources.MentionTextSource.username] + * equal to [username] + * * Any [dev.inmo.tgbotapi.types.message.textsources.TextMentionTextSource] with [dev.inmo.tgbotapi.types.message.textsources.TextMentionTextSource.user] + * with the same [username] + */ +fun TextedContent.isWithMention(username: Username) = textSources.any { + it.whenMentionTextSource { + it.username == username + } ?: it.whenTextMentionTextSource { + it.user.username == username + } ?: false +} + +/** + * Check, that [TextedContent.textSources] contains: + * + * * Any [dev.inmo.tgbotapi.types.message.textsources.TextMentionTextSource] with [dev.inmo.tgbotapi.types.message.textsources.TextMentionTextSource.user] + * with the same [userId] + */ +fun TextedContent.isWithTextMention(userId: UserId) = textSources.any { + it.whenTextMentionTextSource { + it.user.id == userId + } ?: false +} + +/** + * Uses [isWithMention] with [user] [Username] (is presented) or [isWithTextMention] with [user] [UserId] to determine + * user mentioning in [this] [CommonMessage] + */ +fun TextedContent.isWithMention(user: User): Boolean = user.username ?.let { username -> isWithMention(username) } == true || isWithTextMention(user.id) + +/** + * Uses [isWithMention] passing [username] as argument to take only messages with [username] mentions or text mentions + */ +fun Flow.filterMentions(username: Username) = filter { + it.isWithMention(username) +} + +/** + * Uses [isWithTextMention] passing [userId] as argument to take only messages with [userId] text mentions + */ +fun Flow.filterTextMentions(userId: UserId) = filter { + it.isWithTextMention(userId) +} + +/** + * Uses [isWithMention] passing [user] as argument to take only messages with [user] mentions or text mentions + */ +fun Flow.filterMentions(user: User) = filter { + it.isWithMention(user) +} + +/** + * Creates cold [Flow] with the messages with [TextedContent] where [username] has been mentioned + * + * @see filterMentions + * @see filterTextMentions + */ +suspend fun BehaviourContext.waitContentWithMentions ( + username: Username, + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null } +) = waitContent(initRequest, errorFactory).mapContent().filterMentions(username) + +/** + * Creates cold [Flow] with the messages with [TextedContent] where [userId] has been mentioned with text + * + * @see filterTextMentions + * @see filterMentions + * @see dev.inmo.tgbotapi.types.message.textsources.TextMentionTextSource + */ +suspend fun BehaviourContext.waitContentWithTextMentions ( + userId: UserId, + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null } +) = waitTextedContent(initRequest, errorFactory).filterTextMentions(userId) + +/** + * Creates cold [Flow] with the messages with [TextedContent] where [user] has been mentioned as text or mentioned + * with text + * + * @see filterMentions + * @see filterTextMentions + */ +suspend fun BehaviourContext.waitContentWithMentions ( + user: User, + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null } +) = waitTextedContent(initRequest, errorFactory).filterMentions(user) diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitMentionMessage.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitMentionMessage.kt new file mode 100644 index 0000000000..27e61ae457 --- /dev/null +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitMentionMessage.kt @@ -0,0 +1,82 @@ +package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations + +import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext +import dev.inmo.tgbotapi.extensions.utils.whenMentionTextSource +import dev.inmo.tgbotapi.extensions.utils.whenTextMentionTextSource +import dev.inmo.tgbotapi.requests.abstracts.Request +import dev.inmo.tgbotapi.types.UserId +import dev.inmo.tgbotapi.types.Username +import dev.inmo.tgbotapi.types.chat.User +import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage +import dev.inmo.tgbotapi.types.message.content.TextedContent +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.filter + +fun CommonMessage.isWithMention(username: Username) = content.isWithMention(username) + +fun CommonMessage.isWithTextMention(userId: UserId) = content.isWithTextMention(userId) + +/** + * Uses [isWithMention] with [user] [Username] (is presented) or [isWithTextMention] with [user] [UserId] to determine + * user mentioning in [this] [CommonMessage] + */ +fun CommonMessage.isWithMention(user: User): Boolean = content.isWithMention(user) + +/** + * Uses [isWithMention] passing [username] as argument to take only messages with [username] mentions or text mentions + */ +fun Flow>.filterMentionsMessages(username: Username) = filter { + it.isWithMention(username) +} + +/** + * Uses [isWithTextMention] passing [userId] as argument to take only messages with [userId] text mentions + */ +fun Flow>.filterTextMentionsMessages(userId: UserId) = filter { + it.isWithTextMention(userId) +} + +/** + * Uses [isWithMention] passing [user] as argument to take only messages with [user] mentions or text mentions + */ +fun Flow>.filterMentionsMessages(user: User) = filter { + it.isWithMention(user) +} + +/** + * Creates cold [Flow] with the messages with [TextedContent] where [username] has been mentioned + * + * @see filterMentions + * @see filterTextMentions + */ +suspend fun BehaviourContext.waitContentMessageWithMentions ( + username: Username, + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null } +) = waitContentMessage(initRequest, errorFactory).mapWithContent().filterMentionsMessages(username) + +/** + * Creates cold [Flow] with the messages with [TextedContent] where [userId] has been mentioned with text + * + * @see filterTextMentions + * @see filterMentions + * @see dev.inmo.tgbotapi.types.message.textsources.TextMentionTextSource + */ +suspend fun BehaviourContext.waitContentMessageWithTextMentions ( + userId: UserId, + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null } +) = waitTextedContentMessage(initRequest, errorFactory).filterTextMentionsMessages(userId) + +/** + * Creates cold [Flow] with the messages with [TextedContent] where [user] has been mentioned as text or mentioned + * with text + * + * @see filterMentions + * @see filterTextMentions + */ +suspend fun BehaviourContext.waitContentMessageWithMentions ( + user: User, + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null } +) = waitTextedContentMessage(initRequest, errorFactory).filterMentionsMessages(user) 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 e6ce8d8a3c..2ff230af77 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.onTextedContent( + initialFilter: CommonMessageFilter? = null, + 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.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/MentionTriggers.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/MentionTriggers.kt new file mode 100644 index 0000000000..1acc11d2dc --- /dev/null +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/MentionTriggers.kt @@ -0,0 +1,357 @@ +package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling + +import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext +import dev.inmo.tgbotapi.extensions.behaviour_builder.CustomBehaviourContextAndTwoTypesReceiver +import dev.inmo.tgbotapi.extensions.behaviour_builder.CustomBehaviourContextAndTypeReceiver +import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.isWithMention +import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.isWithTextMention +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.AnyMarkerFactory +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times +import dev.inmo.tgbotapi.types.UserId +import dev.inmo.tgbotapi.types.Username +import dev.inmo.tgbotapi.types.chat.User +import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage +import dev.inmo.tgbotapi.types.message.content.AnimationContent +import dev.inmo.tgbotapi.types.message.content.AudioContent +import dev.inmo.tgbotapi.types.message.content.DocumentContent +import dev.inmo.tgbotapi.types.message.content.MediaGroupContent +import dev.inmo.tgbotapi.types.message.content.MediaGroupPartContent +import dev.inmo.tgbotapi.types.message.content.PhotoContent +import dev.inmo.tgbotapi.types.message.content.TextContent +import dev.inmo.tgbotapi.types.message.content.TextedContent +import dev.inmo.tgbotapi.types.message.content.VideoContent +import dev.inmo.tgbotapi.types.message.content.VisualMediaGroupPartContent +import dev.inmo.tgbotapi.types.message.content.VoiceContent +import dev.inmo.tgbotapi.types.update.abstracts.Update + +internal suspend inline fun BC.onMention( + username: Username, + initialFilter: CommonMessageFilter? = null, + noinline subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + noinline scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onContentMessageWithType( + initialFilter * { + it.content.isWithMention(username) + }, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +internal suspend inline fun BC.onTextMention( + userId: UserId, + initialFilter: CommonMessageFilter? = null, + noinline subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + noinline scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onContentMessageWithType( + initialFilter * { + it.content.isWithTextMention(userId) + }, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +internal suspend inline fun BC.onMention( + user: User, + initialFilter: CommonMessageFilter? = null, + noinline subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + noinline scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onContentMessageWithType( + initialFilter * { + it.content.isWithMention(user) + }, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + + +suspend fun BC.onMentionWithAnyContent( + username: Username, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onMention(username, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BC.onTextMentionWithAnyContent( + userId: UserId, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onTextMention(userId, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BC.onMentionWithAnyContent( + user: User, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onMention(user, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + + + +suspend fun BC.onMentionWithVoiceContent( + username: Username, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onMention(username, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BC.onTextMentionWithVoiceContent( + userId: UserId, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onTextMention(userId, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BC.onMentionWithVoiceContent( + user: User, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onMention(user, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + + + +suspend fun BC.onMentionWithMediaGroupContent( + username: Username, + initialFilter: CommonMessageFilter>? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver>, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver>> +) = onMention(username, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BC.onTextMentionWithMediaGroupContent( + userId: UserId, + initialFilter: CommonMessageFilter>? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver>, Update>? = null, + markerFactory: MarkerFactory>, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver>> +) = onTextMention(userId, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BC.onMentionWithMediaGroupContent( + user: User, + initialFilter: CommonMessageFilter>? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver>, Update>? = null, + markerFactory: MarkerFactory>, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver>> +) = onMention(user, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + + + +suspend fun BC.onMentionWithMediaGroupPartContent( + username: Username, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onMention(username, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BC.onTextMentionWithMediaGroupPartContent( + userId: UserId, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onTextMention(userId, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BC.onMentionWithMediaGroupPartContent( + user: User, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onMention(user, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + + + +suspend fun BC.onMentionWithAudioContent( + username: Username, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onMention(username, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BC.onTextMentionWithAudioContent( + userId: UserId, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onTextMention(userId, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BC.onMentionWithAudioContent( + user: User, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onMention(user, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + + + +suspend fun BC.onMentionWithDocumentContent( + username: Username, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onMention(username, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BC.onTextMentionWithDocumentContent( + userId: UserId, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onTextMention(userId, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BC.onMentionWithDocumentContent( + user: User, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onMention(user, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + + + +suspend fun BC.onMentionWithVisualMediaGroupPartContent( + username: Username, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onMention(username, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BC.onTextMentionWithVisualMediaGroupPartContent( + userId: UserId, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onTextMention(userId, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BC.onMentionWithVisualMediaGroupPartContent( + user: User, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onMention(user, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + + + +suspend fun BC.onMentionWithVideoContent( + username: Username, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onMention(username, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BC.onTextMentionWithVideoContent( + userId: UserId, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onTextMention(userId, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BC.onMentionWithVideoContent( + user: User, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onMention(user, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + + + +suspend fun BC.onMentionWithPhotoContent( + username: Username, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onMention(username, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BC.onTextMentionWithPhotoContent( + userId: UserId, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onTextMention(userId, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BC.onMentionWithPhotoContent( + user: User, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onMention(user, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + + + +suspend fun BC.onMentionWithAnimationContent( + username: Username, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onMention(username, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BC.onTextMentionWithAnimationContent( + userId: UserId, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onTextMention(userId, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BC.onMentionWithAnimationContent( + user: User, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onMention(user, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + + + +suspend fun BC.onMentionWithTextContent( + username: Username, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onMention(username, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BC.onTextMentionWithTextContent( + userId: UserId, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onTextMention(userId, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BC.onMentionWithTextContent( + user: User, + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update>? = null, + markerFactory: MarkerFactory, Any> = AnyMarkerFactory(), + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +) = onMention(user, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/Abstracts.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/Abstracts.kt index 9d21571e14..9d6eaac1c9 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/Abstracts.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/Abstracts.kt @@ -1,6 +1,7 @@ package dev.inmo.tgbotapi.types.message.content import dev.inmo.tgbotapi.abstracts.SpoilerableData +import dev.inmo.tgbotapi.abstracts.TextedInput import dev.inmo.tgbotapi.utils.internal.ClassCastsIncluded import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.types.ChatIdentifier @@ -51,6 +52,18 @@ sealed interface MessageContent: ResendableContent { additionalBuilder() } + + polymorphic(TextedContent::class) { + subclass(TextContent::class) + subclass(VoiceContent::class) + subclass(MediaGroupContent::class) + subclass(AudioContent::class) + subclass(DocumentContent::class) + subclass(VideoContent::class) + subclass(PhotoContent::class) + subclass(AnimationContent::class) + } + polymorphic(MediaCollectionContent::class) { subclass(PhotoContent::class) @@ -115,6 +128,11 @@ sealed interface MediaCollectionContent: MessageContent, M val mediaCollection: List } +/** + * All the subtypes of this content will have [text] and [textSources] fields + */ +sealed interface TextedContent : MessageContent, TextedInput + sealed interface MediaContent: MessageContent { val media: TelegramMediaFile fun asTelegramMedia(): TelegramMedia diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/AbstractsMedia.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/AbstractsMedia.kt index 724552a98f..2b7cd80eaf 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/AbstractsMedia.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/AbstractsMedia.kt @@ -22,7 +22,7 @@ sealed interface DocumentMediaGroupPartContent : MediaGroupPartContent { override fun toMediaGroupMemberTelegramMedia(): DocumentMediaGroupMemberTelegramMedia } -sealed interface TextedMediaContent : MediaContent, TextedInput +sealed interface TextedMediaContent : TextedContent, MediaContent sealed interface MediaGroupCollectionContent : TextedMediaContent { @Serializable diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/TextContent.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/TextContent.kt index d16933944b..ff83c6abc2 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/TextContent.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/TextContent.kt @@ -15,7 +15,7 @@ import kotlinx.serialization.Serializable data class TextContent( override val text: String, override val textSources: TextSourcesList = emptyList(), -) : MessageContent, TextedInput { +) : TextedContent { override fun createResend( chatId: ChatIdentifier, messageThreadId: MessageThreadId?, 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 9ed6c11430..7cd305fdff 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 @@ -2,6 +2,8 @@ package dev.inmo.tgbotapi.types.message.content import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage +typealias TextedMessage = CommonMessage + typealias InvoiceMessage = CommonMessage typealias VenueMessage = CommonMessage typealias GameMessage = CommonMessage From f07a1794483cafc8e1f3ba2ad964bbf81ceb2305 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 18 May 2023 13:06:41 +0600 Subject: [PATCH 5/6] InputFile kdocs improvements --- CHANGELOG.md | 2 ++ .../tgbotapi/requests/abstracts/InputFile.kt | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 747aa60508..c710e3abd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ * `Versions`: * `Serialization`: `1.5.0` -> `1.5.1` * `MicroUtils`: `0.18.1` -> `0.18.4` +* `Core`: + * Actualize kdocs in `InputFile` * `BehaviourBuilder`: * Now it is possible to use `waitMediaContent`/`waitMediaContentMessage`/`onMediaContent` * Add `onMention`/`waitMention` functionality diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/abstracts/InputFile.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/abstracts/InputFile.kt index 67b126c235..8aeebbfd18 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/abstracts/InputFile.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/abstracts/InputFile.kt @@ -21,6 +21,11 @@ import kotlinx.serialization.encoding.Encoder * @see ByteArray.asMultipartFile * @see ByteReadChannel.asMultipartFile * @see ByteReadChannelAllocator.asMultipartFile + * + * @see fromInput + * @see fromFile + * @see fromId + * @see fromUrl */ @Serializable(InputFileSerializer::class) sealed class InputFile { @@ -29,9 +34,24 @@ sealed class InputFile { companion object { operator fun invoke(file: MPPFile) = file.asMultipartFile() + /** + * Creates [MultipartFile] based on incoming [filename] and [inputSource] + */ fun fromInput(filename: String, inputSource: () -> Input) = MultipartFile(filename, inputSource) + + /** + * Creates [MultipartFile] based on incoming [MPPFile] (common File in java, for example) + */ fun fromFile(file: MPPFile) = invoke(file) + + /** + * Creates [FileId] from the incomming [id] [String] with believe that it is [FileId] + */ fun fromId(id: String) = FileId(id) + + /** + * Creates [FileUrl] from the incomming [url] [String] + */ fun fromUrl(url: String) = FileUrl(url) } } From 65bcf8351791440b8a6fe8becde913723eed17a5 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Fri, 19 May 2023 22:42:42 +0600 Subject: [PATCH 6/6] update ClassCasts --- .../inmo/tgbotapi/extensions/utils/ClassCastsNew.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) 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 0f55cd2733..72626842e5 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 @@ -329,6 +329,7 @@ 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.TextContent +import dev.inmo.tgbotapi.types.message.content.TextedContent import dev.inmo.tgbotapi.types.message.content.TextedMediaContent import dev.inmo.tgbotapi.types.message.content.VenueContent import dev.inmo.tgbotapi.types.message.content.VideoContent @@ -3712,6 +3713,15 @@ public inline fun ResendableContent.ifMediaCollectionContent(block: (MediaCollectionContent) -> T): T? = mediaCollectionContentOrNull() ?.let(block) +public inline fun ResendableContent.textedContentOrNull(): TextedContent? = this as? + dev.inmo.tgbotapi.types.message.content.TextedContent + +public inline fun ResendableContent.textedContentOrThrow(): TextedContent = this as + dev.inmo.tgbotapi.types.message.content.TextedContent + +public inline fun ResendableContent.ifTextedContent(block: (TextedContent) -> T): T? = + textedContentOrNull() ?.let(block) + public inline fun ResendableContent.mediaContentOrNull(): MediaContent? = this as? dev.inmo.tgbotapi.types.message.content.MediaContent