diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitCommandsMessages.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitCommandsMessages.kt index 002f5ef291..a975055845 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitCommandsMessages.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitCommandsMessages.kt @@ -33,6 +33,12 @@ suspend fun BehaviourContext.waitCommandMessage( } } +suspend fun BehaviourContext.waitCommandMessage( + command: String, + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null } +) = waitCommandMessage(Regex(command), initRequest, errorFactory) + fun Flow>.requireCommandAtStart() = filter { (it.content.textSources.firstOrNull() as? BotCommandTextSource) != null } diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitDeepLinks.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitDeepLinks.kt new file mode 100644 index 0000000000..51aa6f3228 --- /dev/null +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitDeepLinks.kt @@ -0,0 +1,23 @@ +package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations + +import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext +import dev.inmo.tgbotapi.extensions.utils.regularTextSourceOrNull +import dev.inmo.tgbotapi.requests.abstracts.Request +import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage +import dev.inmo.tgbotapi.types.message.content.TextContent +import dev.inmo.tgbotapi.types.message.textsources.RegularTextSource +import kotlinx.coroutines.flow.* + +suspend fun BehaviourContext.waitDeepLinks( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, +): Flow, String>> = waitCommandMessage( + "start", + initRequest, + errorFactory +) + .requireSingleCommand() + .requireCommandAtStart() + .flattenCommandsWithParams().mapNotNull { + it.first to (it.second.second.singleOrNull() ?.regularTextSourceOrNull() ?.source ?: return@mapNotNull null) + } diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/DeepLinkHandling.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/DeepLinkHandling.kt new file mode 100644 index 0000000000..00029132c6 --- /dev/null +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/DeepLinkHandling.kt @@ -0,0 +1,41 @@ +@file:Suppress("unused") + +package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling + +import dev.inmo.micro_utils.coroutines.* +import dev.inmo.tgbotapi.extensions.behaviour_builder.* +import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitDeepLinks +import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.CommonMessageFilterExcludeMediaGroups +import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.MessageFilterByChat +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByChatMessageMarkerFactory +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times +import dev.inmo.tgbotapi.extensions.utils.* +import dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithParams +import dev.inmo.tgbotapi.types.message.content.TextContent +import dev.inmo.tgbotapi.types.message.content.TextMessage +import dev.inmo.tgbotapi.types.message.textsources.RegularTextSource +import dev.inmo.tgbotapi.types.update.abstracts.Update +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.filter + +suspend fun BC.onDeepLink( + initialFilter: SimpleFilter>? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update> = { (message, _), update -> MessageFilterByChat(this, message, update) }, + markerFactory: MarkerFactory, Any> = MarkerFactory { (message, _) -> ByChatMessageMarkerFactory(message) }, + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +): Job = on( + markerFactory, + SimpleFilter> { (message, _) -> + message.content.textSources.size == 2 + && message.content.textSources.firstOrNull() ?.asBotCommandTextSource() ?.command == "start" + && message.content.textSources.getOrNull(1) is RegularTextSource + } * initialFilter, + subcontextUpdatesFilter, + scenarioReceiver, +) { + (it.messageUpdateOrNull()) ?.data ?.commonMessageOrNull() ?.withContentOrNull() ?.let { message -> + message to message.content.textSources[1].source + } ?.let(::listOfNotNull) +} diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/SimpleFilter.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/SimpleFilter.kt index fb918ffb93..e4dac61c93 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/SimpleFilter.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/SimpleFilter.kt @@ -4,6 +4,7 @@ fun interface SimpleFilter { suspend operator fun invoke(o: T): Boolean } val TrueSimpleFilter = SimpleFilter { true } +val FalseSimpleFilter = SimpleFilter { false } /** * @return [SimpleFilter] which will return true in case when all the items in incoming data passed [this] filter @@ -28,21 +29,29 @@ fun SimpleFilter.listNone() = SimpleFilter> { /** * Makes an AND (&&) operation between [this] and [other] + * + * * When both arguments are null, [TrueSimpleFilter] will be returned */ -operator fun SimpleFilter?.times(other: SimpleFilter): SimpleFilter = this ?.let { - SimpleFilter { - this(it) && other(it) - } -} ?: other +infix operator fun SimpleFilter?.times(other: SimpleFilter?): SimpleFilter = this ?.let { + other ?.let { + SimpleFilter { + this(it) && other(it) + } + } ?: it +} ?: other ?: TrueSimpleFilter /** * Makes an OR (||) operation between [this] and [other] + * + * * When both arguments are null, [TrueSimpleFilter] will be returned */ -operator fun SimpleFilter?.plus(other: SimpleFilter): SimpleFilter = this ?.let { - SimpleFilter { - this(it) || other(it) - } -} ?: other +infix operator fun SimpleFilter?.plus(other: SimpleFilter?): SimpleFilter = this ?.let { + other ?.let { + SimpleFilter { + this(it) || other(it) + } + } ?: it +} ?: other ?: TrueSimpleFilter /** * Reverse results of [this]