diff --git a/CHANGELOG.md b/CHANGELOG.md index fe4e425156..91ad059a41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # TelegramBotAPI changelog +## 0.38.23 + +* `BehaviourHandler`: + * Add support of fallback triggers (fix of [#560](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/560)) + ## 0.38.22 * `Core`: diff --git a/gradle.properties b/gradle.properties index d804f6b631..ca7b035456 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,6 +20,6 @@ javax_activation_version=1.1.1 dokka_version=1.6.10 library_group=dev.inmo -library_version=0.38.22 +library_version=0.38.23 github_release_plugin_version=2.3.7 diff --git a/tgbotapi.behaviour_builder.fsm/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContextWithFSM.kt b/tgbotapi.behaviour_builder.fsm/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContextWithFSM.kt index 2bb6b3ea89..efac220bd1 100644 --- a/tgbotapi.behaviour_builder.fsm/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContextWithFSM.kt +++ b/tgbotapi.behaviour_builder.fsm/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContextWithFSM.kt @@ -6,6 +6,7 @@ import dev.inmo.micro_utils.fsm.common.* import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.types.update.abstracts.Update import dev.inmo.micro_utils.coroutines.accumulatorFlow +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers_registrar.TriggersHolder import kotlinx.coroutines.* import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.flow.* @@ -59,6 +60,7 @@ interface BehaviourContextWithFSM : BehaviourContext, StatesMachine?, + triggersHolder: TriggersHolder, updatesFilter: BehaviourContextAndTypeReceiver? ): BehaviourContextWithFSM @@ -178,9 +180,10 @@ class DefaultBehaviourContextWithFSM( broadcastChannelsSize: Int, onBufferOverflow: BufferOverflow, upstreamUpdatesFlow: Flow?, + triggersHolder: TriggersHolder, updatesFilter: BehaviourContextAndTypeReceiver? ): DefaultBehaviourContextWithFSM = BehaviourContextWithFSM( - behaviourContext.copy(bot, scope, broadcastChannelsSize, onBufferOverflow, upstreamUpdatesFlow, updatesFilter), + behaviourContext.copy(bot, scope, broadcastChannelsSize, onBufferOverflow, upstreamUpdatesFlow, triggersHolder, updatesFilter), handlers, statesManager ) diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContext.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContext.kt index a5d9a0e73d..b6aaf4f04a 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContext.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContext.kt @@ -4,9 +4,9 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder import dev.inmo.micro_utils.coroutines.* import dev.inmo.tgbotapi.bot.TelegramBot +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers_registrar.TriggersHolder import dev.inmo.tgbotapi.types.update.abstracts.Update import dev.inmo.tgbotapi.updateshandlers.* -import dev.inmo.tgbotapi.utils.RiskFeature import kotlinx.coroutines.* import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.flow.* @@ -47,12 +47,15 @@ interface BehaviourContext : FlowsUpdatesFilter, TelegramBot, CoroutineScope { val flowsUpdatesFilter: FlowsUpdatesFilter get() = this + val triggersHolder: TriggersHolder + fun copy( bot: TelegramBot = this.bot, scope: CoroutineScope = this.scope, broadcastChannelsSize: Int = 100, onBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND, upstreamUpdatesFlow: Flow? = null, + triggersHolder: TriggersHolder = TriggersHolder(), updatesFilter: BehaviourContextAndTypeReceiver? = null ): BehaviourContext } @@ -63,6 +66,7 @@ class DefaultBehaviourContext( broadcastChannelsSize: Int = 100, onBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND, private val upstreamUpdatesFlow: Flow? = null, + override val triggersHolder: TriggersHolder = TriggersHolder(), private val updatesFilter: BehaviourContextAndTypeReceiver? = null ) : AbstractFlowsUpdatesFilter(), TelegramBot by bot, CoroutineScope by scope, BehaviourContext { @@ -89,22 +93,25 @@ class DefaultBehaviourContext( broadcastChannelsSize: Int, onBufferOverflow: BufferOverflow, upstreamUpdatesFlow: Flow?, + triggersHolder: TriggersHolder, updatesFilter: BehaviourContextAndTypeReceiver? - ): DefaultBehaviourContext = DefaultBehaviourContext(bot, scope, broadcastChannelsSize, onBufferOverflow, upstreamUpdatesFlow, updatesFilter) + ): DefaultBehaviourContext = DefaultBehaviourContext(bot, scope, broadcastChannelsSize, onBufferOverflow, upstreamUpdatesFlow, triggersHolder, updatesFilter) } fun BehaviourContext( bot: TelegramBot, scope: CoroutineScope, - flowsUpdatesFilter: FlowsUpdatesFilter = FlowsUpdatesFilter() -) = DefaultBehaviourContext(bot, scope, upstreamUpdatesFlow = flowsUpdatesFilter.allUpdatesFlow) + flowsUpdatesFilter: FlowsUpdatesFilter = FlowsUpdatesFilter(), + triggersHolder: TriggersHolder = TriggersHolder(), +) = DefaultBehaviourContext(bot, scope, upstreamUpdatesFlow = flowsUpdatesFilter.allUpdatesFlow, triggersHolder = triggersHolder) inline fun BehaviourContext( bot: TelegramBot, scope: CoroutineScope, flowsUpdatesFilter: FlowsUpdatesFilter = FlowsUpdatesFilter(), + triggersHolder: TriggersHolder = TriggersHolder(), crossinline block: BehaviourContext.() -> T -) = DefaultBehaviourContext(bot, scope, upstreamUpdatesFlow = flowsUpdatesFilter.allUpdatesFlow).run(block) +) = DefaultBehaviourContext(bot, scope, upstreamUpdatesFlow = flowsUpdatesFilter.allUpdatesFlow, triggersHolder = triggersHolder).run(block) /** * Creates new one [BehaviourContext], adding subsequent [FlowsUpdatesFilter] in case [updatesFilter] is provided and @@ -115,6 +122,7 @@ suspend fun BC.doInSubContextWithUpdatesFilter( stopOnCompletion: Boolean = true, updatesUpstreamFlow: Flow = allUpdatesFlow, scope: CoroutineScope = LinkedSupervisorScope(), + triggersHolder: TriggersHolder = this.triggersHolder, behaviourContextReceiver: CustomBehaviourContextReceiver ): T { val newContext = copy( @@ -126,7 +134,8 @@ suspend fun BC.doInSubContextWithUpdatesFilter( } ?: true } }, - upstreamUpdatesFlow = updatesUpstreamFlow + upstreamUpdatesFlow = updatesUpstreamFlow, + triggersHolder = triggersHolder ) as BC return withContext(currentCoroutineContext()) { newContext.behaviourContextReceiver().also { if (stopOnCompletion) newContext.stop() } @@ -137,8 +146,9 @@ suspend fun BehaviourContext.doInSubContext( stopOnCompletion: Boolean = true, updatesUpstreamFlow: Flow = allUpdatesFlow, scope: CoroutineScope = LinkedSupervisorScope(), + triggersHolder: TriggersHolder = this.triggersHolder, behaviourContextReceiver: BehaviourContextReceiver -) = doInSubContextWithUpdatesFilter(updatesFilter = null, stopOnCompletion, updatesUpstreamFlow, scope, behaviourContextReceiver) +) = doInSubContextWithUpdatesFilter(updatesFilter = null, stopOnCompletion, updatesUpstreamFlow, scope, triggersHolder, behaviourContextReceiver) /** * This method will cancel ALL subsequent contexts, expectations and waiters diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitChatJoinRequest.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitChatJoinRequest.kt index f3efaaf195..d6cc34efa3 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitChatJoinRequest.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitChatJoinRequest.kt @@ -2,11 +2,9 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter -import dev.inmo.tgbotapi.extensions.utils.* +import dev.inmo.tgbotapi.extensions.utils.asChatJoinRequestUpdate import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.types.ChatJoinRequest -import dev.inmo.tgbotapi.types.payments.PreCheckoutQuery -import dev.inmo.tgbotapi.types.payments.ShippingQuery import kotlinx.coroutines.flow.toList typealias ChatJoinRequestsMapper = suspend ChatJoinRequest.() -> ChatJoinRequest? diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitChosenInlineResult.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitChosenInlineResult.kt index 3b277f24f6..940f68ea3b 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitChosenInlineResult.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitChosenInlineResult.kt @@ -2,10 +2,9 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter -import dev.inmo.tgbotapi.extensions.utils.* +import dev.inmo.tgbotapi.extensions.utils.asChosenInlineResultUpdate import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.types.InlineQueries.ChosenInlineResult.* -import dev.inmo.tgbotapi.types.polls.* import kotlinx.coroutines.flow.toList typealias ChosenInlineResultMapper = suspend T.() -> T? 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 5960fd0c4a..f062bcd893 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 @@ -9,12 +9,9 @@ import dev.inmo.tgbotapi.extensions.utils.withContent import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage import dev.inmo.tgbotapi.types.message.content.* -import dev.inmo.tgbotapi.types.message.content.abstracts.* +import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent +import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent import dev.inmo.tgbotapi.types.message.content.media.* -import dev.inmo.tgbotapi.types.message.content.media.AudioMediaGroupContent -import dev.inmo.tgbotapi.types.message.content.media.DocumentMediaGroupContent -import dev.inmo.tgbotapi.types.message.content.media.MediaGroupContent -import dev.inmo.tgbotapi.types.message.content.media.VisualMediaGroupContent import dev.inmo.tgbotapi.types.message.payments.InvoiceContent import dev.inmo.tgbotapi.types.update.MediaGroupUpdates.SentMediaGroupUpdate import dev.inmo.tgbotapi.types.update.abstracts.BaseSentMessageUpdate 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 914087e158..ca0dc07260 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 @@ -9,12 +9,9 @@ import dev.inmo.tgbotapi.extensions.utils.withContent import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage import dev.inmo.tgbotapi.types.message.content.* -import dev.inmo.tgbotapi.types.message.content.abstracts.* +import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent +import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent import dev.inmo.tgbotapi.types.message.content.media.* -import dev.inmo.tgbotapi.types.message.content.media.AudioMediaGroupContent -import dev.inmo.tgbotapi.types.message.content.media.DocumentMediaGroupContent -import dev.inmo.tgbotapi.types.message.content.media.MediaGroupContent -import dev.inmo.tgbotapi.types.message.content.media.VisualMediaGroupContent import dev.inmo.tgbotapi.types.message.payments.InvoiceContent import dev.inmo.tgbotapi.types.update.MediaGroupUpdates.SentMediaGroupUpdate import dev.inmo.tgbotapi.types.update.abstracts.BaseSentMessageUpdate diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitEditedContent.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitEditedContent.kt index eab0ec1962..ba73dd1d06 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitEditedContent.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitEditedContent.kt @@ -10,12 +10,9 @@ import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage import dev.inmo.tgbotapi.types.message.abstracts.MediaGroupMessage import dev.inmo.tgbotapi.types.message.content.* -import dev.inmo.tgbotapi.types.message.content.abstracts.* +import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent +import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent import dev.inmo.tgbotapi.types.message.content.media.* -import dev.inmo.tgbotapi.types.message.content.media.AudioMediaGroupContent -import dev.inmo.tgbotapi.types.message.content.media.DocumentMediaGroupContent -import dev.inmo.tgbotapi.types.message.content.media.MediaGroupContent -import dev.inmo.tgbotapi.types.message.content.media.VisualMediaGroupContent import dev.inmo.tgbotapi.types.message.payments.InvoiceContent import dev.inmo.tgbotapi.types.update.abstracts.BaseEditMessageUpdate import kotlinx.coroutines.flow.toList diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitMediaGroup.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitMediaGroup.kt index 353a0be526..990b5e41fe 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitMediaGroup.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitMediaGroup.kt @@ -4,12 +4,7 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext import dev.inmo.tgbotapi.extensions.utils.asSentMediaGroupUpdate import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.types.message.abstracts.MediaGroupMessage -import dev.inmo.tgbotapi.types.message.content.abstracts.* import dev.inmo.tgbotapi.types.message.content.media.* -import dev.inmo.tgbotapi.types.message.content.media.AudioMediaGroupContent -import dev.inmo.tgbotapi.types.message.content.media.DocumentMediaGroupContent -import dev.inmo.tgbotapi.types.message.content.media.MediaGroupContent -import dev.inmo.tgbotapi.types.message.content.media.VisualMediaGroupContent import dev.inmo.tgbotapi.utils.PreviewFeature import kotlinx.coroutines.flow.take import kotlinx.coroutines.flow.toList diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitPollAnswers.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitPollAnswers.kt index 718bdd4c89..1775f74369 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitPollAnswers.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitPollAnswers.kt @@ -2,9 +2,9 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter -import dev.inmo.tgbotapi.extensions.utils.* +import dev.inmo.tgbotapi.extensions.utils.asPollAnswerUpdate import dev.inmo.tgbotapi.requests.abstracts.Request -import dev.inmo.tgbotapi.types.polls.* +import dev.inmo.tgbotapi.types.polls.PollAnswer import kotlinx.coroutines.flow.toList typealias PollAnswerMapper = suspend PollAnswer.() -> PollAnswer? diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitPollUpdates.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitPollUpdates.kt index 0aebcb4acd..7f2b980034 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitPollUpdates.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitPollUpdates.kt @@ -2,7 +2,7 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter -import dev.inmo.tgbotapi.extensions.utils.* +import dev.inmo.tgbotapi.extensions.utils.asPollUpdate import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.types.polls.* import kotlinx.coroutines.flow.toList diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitPreCheckoutQuery.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitPreCheckoutQuery.kt index d2c8cf9612..81ea5b23a2 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitPreCheckoutQuery.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitPreCheckoutQuery.kt @@ -3,10 +3,8 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter import dev.inmo.tgbotapi.extensions.utils.asPreCheckoutQueryUpdate -import dev.inmo.tgbotapi.extensions.utils.asShippingQueryUpdate import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.types.payments.PreCheckoutQuery -import dev.inmo.tgbotapi.types.payments.ShippingQuery import kotlinx.coroutines.flow.toList typealias PreCheckoutQueryMapper = suspend PreCheckoutQuery.() -> PreCheckoutQuery? diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/CallbackQueryTriggers.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/CallbackQueryTriggers.kt index 4689320dd2..ca7fa9204c 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/CallbackQueryTriggers.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/CallbackQueryTriggers.kt @@ -2,6 +2,8 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling +import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions +import dev.inmo.micro_utils.coroutines.runCatchingSafely import dev.inmo.tgbotapi.extensions.behaviour_builder.* import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.CallbackQueryFilterByUser import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter @@ -11,6 +13,7 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus import dev.inmo.tgbotapi.extensions.utils.asCallbackQueryUpdate import dev.inmo.tgbotapi.types.CallbackQuery.* import dev.inmo.tgbotapi.types.update.abstracts.Update +import kotlinx.coroutines.Job internal suspend inline fun BC.onCallbackQuery( noinline initialFilter: SimpleFilter? = null, @@ -21,6 +24,48 @@ internal suspend inline fun B (it.asCallbackQueryUpdate() ?.data as? T) ?.let(::listOfNotNull) } +/** + * @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call + * @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example, + * this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage]. + * Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own. + * Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times] + * to combinate several filters + * @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously + * in one "stream". Output of [markerFactory] will be used as a key for "stream" + * @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that + * data + */ +internal suspend inline fun BC.onDataCallbackQueryCounted( + noinline initialFilter: SimpleFilter? = null, + noinline subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver? = CallbackQueryFilterByUser, + markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, + noinline scenarioReceiver: CustomBehaviourContextAndTypeReceiver +): Job { + val newInitialFilter = SimpleFilter { + it is T && initialFilter ?.invoke(it) ?: true + } + return runCatchingSafely { + onCallbackQuery ( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver + ) + }.onFailure { + triggersHolder.handleableCallbackQueriesDataHolder.unregisterHandleable(newInitialFilter) + }.onSuccess { + triggersHolder.handleableCallbackQueriesDataHolder.registerHandleable(newInitialFilter) + it.invokeOnCompletion { + runCatching { + launchSafelyWithoutExceptions { + triggersHolder.handleableCallbackQueriesDataHolder.unregisterHandleable(newInitialFilter) + } + } + } + }.getOrThrow() +} + /** * @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, @@ -38,7 +83,7 @@ suspend fun BC.onDataCallbackQuery( subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver? = CallbackQueryFilterByUser, markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, scenarioReceiver: CustomBehaviourContextAndTypeReceiver -) = onCallbackQuery( +) = onDataCallbackQueryCounted( initialFilter, subcontextUpdatesFilter, markerFactory, @@ -166,7 +211,7 @@ suspend fun BC.onInlineMessageIdDataCallbackQuery( subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver? = CallbackQueryFilterByUser, markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, scenarioReceiver: CustomBehaviourContextAndTypeReceiver -) = onCallbackQuery( +) = onDataCallbackQueryCounted( initialFilter, subcontextUpdatesFilter, markerFactory, @@ -294,7 +339,7 @@ suspend fun BC.onMessageDataCallbackQuery( subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver? = CallbackQueryFilterByUser, markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, scenarioReceiver: CustomBehaviourContextAndTypeReceiver -) = onCallbackQuery( +) = onDataCallbackQueryCounted( initialFilter, subcontextUpdatesFilter, markerFactory, diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/CallbackQueryTriggersUnhandled.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/CallbackQueryTriggersUnhandled.kt new file mode 100644 index 0000000000..58665be972 --- /dev/null +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/CallbackQueryTriggersUnhandled.kt @@ -0,0 +1,83 @@ +@file:Suppress("unused") + +package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling + +import dev.inmo.tgbotapi.extensions.behaviour_builder.* +import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.CallbackQueryFilterByUser +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.* +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByUserCallbackQueryMarkerFactory +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory +import dev.inmo.tgbotapi.types.CallbackQuery.* +import dev.inmo.tgbotapi.types.update.abstracts.Update + +/** + * @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.onUnhandledDataCallbackQuery( + initialFilter: SimpleFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver? = CallbackQueryFilterByUser, + markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, + scenarioReceiver: CustomBehaviourContextAndTypeReceiver +) = onCallbackQuery ( + initialFilter * !SimpleFilter { triggersHolder.handleableCallbackQueriesDataHolder.isHandled(it) }, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call + * @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example, + * this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage]. + * Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own. + * Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times] + * to combinate several filters + * @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously + * in one "stream". Output of [markerFactory] will be used as a key for "stream" + * @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that + * data + */ +suspend fun BC.onUnhandledInlineMessageIdDataCallbackQuery( + initialFilter: SimpleFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver? = CallbackQueryFilterByUser, + markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, + scenarioReceiver: CustomBehaviourContextAndTypeReceiver +) = onCallbackQuery ( + initialFilter * !SimpleFilter { triggersHolder.handleableCallbackQueriesDataHolder.isHandled(it) }, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call + * @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example, + * this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage]. + * Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own. + * Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times] + * to combinate several filters + * @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously + * in one "stream". Output of [markerFactory] will be used as a key for "stream" + * @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that + * data + */ +suspend fun BC.onUnhandledMessageDataCallbackQuery( + initialFilter: SimpleFilter? = null, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver? = CallbackQueryFilterByUser, + markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, + scenarioReceiver: CustomBehaviourContextAndTypeReceiver +) = onCallbackQuery( + initialFilter * !SimpleFilter { triggersHolder.handleableCallbackQueriesDataHolder.isHandled(it) }, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ChatJoinRequestTriggers.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ChatJoinRequestTriggers.kt index b201725d57..a49c8ce57a 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ChatJoinRequestTriggers.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ChatJoinRequestTriggers.kt @@ -1,13 +1,12 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling import dev.inmo.tgbotapi.extensions.behaviour_builder.* -import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.* +import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.ChatJoinRequestFilterByChat import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter -import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.* +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByChatChatJoinRequestMarkerFactory +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory import dev.inmo.tgbotapi.extensions.utils.asChatJoinRequestUpdate -import dev.inmo.tgbotapi.extensions.utils.asShippingQueryUpdate import dev.inmo.tgbotapi.types.ChatJoinRequest -import dev.inmo.tgbotapi.types.payments.ShippingQuery import dev.inmo.tgbotapi.types.update.abstracts.Update /** diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ChosenInlineResultTriggers.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ChosenInlineResultTriggers.kt index c2689cec06..84704e5492 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ChosenInlineResultTriggers.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ChosenInlineResultTriggers.kt @@ -4,11 +4,10 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling import dev.inmo.tgbotapi.extensions.behaviour_builder.* import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter -import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.* +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByUserIdChosenInlineResultMarkerFactory +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory import dev.inmo.tgbotapi.extensions.utils.asChosenInlineResultUpdate -import dev.inmo.tgbotapi.extensions.utils.asPollUpdate import dev.inmo.tgbotapi.types.InlineQueries.ChosenInlineResult.* -import dev.inmo.tgbotapi.types.polls.* import dev.inmo.tgbotapi.types.update.abstracts.Update internal suspend inline fun BC.onChosenInlineResultBase( diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/CommandHandling.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/CommandHandling.kt index ad04efa0f2..b1943ce5ec 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/CommandHandling.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/CommandHandling.kt @@ -2,6 +2,8 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling +import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions +import dev.inmo.micro_utils.coroutines.runCatchingSafely import dev.inmo.tgbotapi.extensions.behaviour_builder.* import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.CommonMessageFilterExcludeMediaGroups import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.MessageFilterByChat @@ -15,8 +17,7 @@ import dev.inmo.tgbotapi.types.message.content.TextContent import dev.inmo.tgbotapi.types.update.abstracts.Update import kotlinx.coroutines.Job - -suspend fun BC.command( +internal suspend fun BC.commandUncounted( commandRegex: Regex, requireOnlyCommandInMessage: Boolean = true, initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, @@ -43,6 +44,35 @@ suspend fun BC.command( scenarioReceiver ) +suspend fun BC.command( + commandRegex: Regex, + requireOnlyCommandInMessage: Boolean = true, + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +): Job = runCatchingSafely { + commandUncounted( + commandRegex, + requireOnlyCommandInMessage, + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver + ) +}.onFailure { + triggersHolder.handleableCommandsHolder.unregisterHandleable(commandRegex) +}.onSuccess { + triggersHolder.handleableCommandsHolder.registerHandleable(commandRegex) + it.invokeOnCompletion { + runCatching { + launchSafelyWithoutExceptions { + triggersHolder.handleableCommandsHolder.unregisterHandleable(commandRegex) + } + } + } +}.getOrThrow() + suspend fun BC.command( command: String, requireOnlyCommandInMessage: Boolean = true, @@ -52,22 +82,22 @@ suspend fun BC.command( scenarioReceiver: CustomBehaviourContextAndTypeReceiver> ) = command(command.toRegex(), requireOnlyCommandInMessage, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) -suspend inline fun BC.onCommand( +suspend fun BC.onCommand( commandRegex: Regex, requireOnlyCommandInMessage: Boolean = true, - noinline initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, - noinline subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, - noinline scenarioReceiver: CustomBehaviourContextAndTypeReceiver> + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> ): Job = command(commandRegex, requireOnlyCommandInMessage, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) -suspend inline fun BC.onCommand( +suspend fun BC.onCommand( command: String, requireOnlyCommandInMessage: Boolean = true, - noinline initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, - noinline subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, - noinline scenarioReceiver: CustomBehaviourContextAndTypeReceiver> + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> ): Job = onCommand(command.toRegex(), requireOnlyCommandInMessage, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) suspend fun BC.commandWithArgs( @@ -104,18 +134,18 @@ suspend fun BC.commandWithArgs( scenarioReceiver = scenarioReceiver ) -suspend inline fun BC.onCommandWithArgs( +suspend fun BC.onCommandWithArgs( commandRegex: Regex, - noinline initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, - noinline subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, - noinline scenarioReceiver: CustomBehaviourContextAndTwoTypesReceiver, Array> + scenarioReceiver: CustomBehaviourContextAndTwoTypesReceiver, Array> ): Job = commandWithArgs(commandRegex, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) -suspend inline fun BC.onCommandWithArgs( +suspend fun BC.onCommandWithArgs( command: String, - noinline initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, - noinline subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, - noinline scenarioReceiver: CustomBehaviourContextAndTwoTypesReceiver, Array> + scenarioReceiver: CustomBehaviourContextAndTwoTypesReceiver, Array> ): Job = onCommandWithArgs(command.toRegex(), initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/CommandHandlingUnhandled.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/CommandHandlingUnhandled.kt new file mode 100644 index 0000000000..6126b19f5f --- /dev/null +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/CommandHandlingUnhandled.kt @@ -0,0 +1,76 @@ +@file:Suppress("unused") + +package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling + +import dev.inmo.tgbotapi.extensions.behaviour_builder.* +import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.CommonMessageFilterExcludeMediaGroups +import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.MessageFilterByChat +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.asBotCommandTextSource +import dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithParams +import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage +import dev.inmo.tgbotapi.types.message.content.TextContent +import dev.inmo.tgbotapi.types.update.abstracts.Update +import kotlinx.coroutines.Job + + +suspend fun BC.unhandledCommand( + requireOnlyCommandInMessage: Boolean = true, + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +): Job = onText( + CommonMessageFilter { message -> + val content = message.content + val textSources = content.textSources + val sizeRequirement = if (requireOnlyCommandInMessage) { + textSources.size == 1 + } else { + true + } + sizeRequirement && textSources.any { + val command = it.asBotCommandTextSource() ?.command ?: return@any false + !triggersHolder.handleableCommandsHolder.isHandled(command) + } + }.let { + initialFilter ?.times(it) ?: it + }, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +suspend fun BC.onUnhandledCommand( + requireOnlyCommandInMessage: Boolean = true, + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: CustomBehaviourContextAndTypeReceiver> +): Job = unhandledCommand(requireOnlyCommandInMessage, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BC.unhandledCommandWithArgs( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: CustomBehaviourContextAndTwoTypesReceiver, Map>> +) = onUnhandledCommand( + requireOnlyCommandInMessage = false, + initialFilter = initialFilter, + subcontextUpdatesFilter = subcontextUpdatesFilter, + markerFactory = markerFactory +) { + val args = it.parseCommandsWithParams().let { commandsWithArgs -> + commandsWithArgs + } + scenarioReceiver(it, args) +} + +suspend fun BC.onUnhandledCommandWithArgs( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: CustomBehaviourContextAndTwoTypesReceiver, Map>> +): Job = unhandledCommandWithArgs(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/MediaGroupTriggers.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/MediaGroupTriggers.kt index 4a00fc3801..5fe819fe55 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/MediaGroupTriggers.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/MediaGroupTriggers.kt @@ -10,10 +10,6 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.Mar import dev.inmo.tgbotapi.extensions.utils.asSentMediaGroupUpdate import dev.inmo.tgbotapi.types.message.abstracts.MediaGroupMessage import dev.inmo.tgbotapi.types.message.content.media.* -import dev.inmo.tgbotapi.types.message.content.media.AudioMediaGroupContent -import dev.inmo.tgbotapi.types.message.content.media.DocumentMediaGroupContent -import dev.inmo.tgbotapi.types.message.content.media.MediaGroupContent -import dev.inmo.tgbotapi.types.message.content.media.VisualMediaGroupContent import dev.inmo.tgbotapi.types.update.abstracts.Update import dev.inmo.tgbotapi.utils.PreviewFeature diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/PollAnswersTriggers.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/PollAnswersTriggers.kt index 15ebf39209..d12b4fa0e2 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/PollAnswersTriggers.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/PollAnswersTriggers.kt @@ -4,10 +4,10 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling import dev.inmo.tgbotapi.extensions.behaviour_builder.* import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter -import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.* +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByIdPollAnswerMarkerFactory +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory import dev.inmo.tgbotapi.extensions.utils.asPollAnswerUpdate -import dev.inmo.tgbotapi.extensions.utils.asPollUpdate -import dev.inmo.tgbotapi.types.polls.* +import dev.inmo.tgbotapi.types.polls.PollAnswer import dev.inmo.tgbotapi.types.update.abstracts.Update internal suspend inline fun BC.onPollAnswered( diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/PollUpdatesTriggers.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/PollUpdatesTriggers.kt index 92d0d652fa..9c73f577ad 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/PollUpdatesTriggers.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/PollUpdatesTriggers.kt @@ -4,7 +4,8 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling import dev.inmo.tgbotapi.extensions.behaviour_builder.* import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter -import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.* +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByIdPollMarkerFactory +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory import dev.inmo.tgbotapi.extensions.utils.asPollUpdate import dev.inmo.tgbotapi.types.polls.* import dev.inmo.tgbotapi.types.update.abstracts.Update diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/PreCheckoutQueryTriggers.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/PreCheckoutQueryTriggers.kt index bcd7b220c5..3df37d6f8f 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/PreCheckoutQueryTriggers.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/PreCheckoutQueryTriggers.kt @@ -1,13 +1,12 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling import dev.inmo.tgbotapi.extensions.behaviour_builder.* -import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.* +import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.PreCheckoutQueryFilterByUser import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter -import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.* +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByUserPreCheckoutQueryMarkerFactory +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory import dev.inmo.tgbotapi.extensions.utils.asPreCheckoutQueryUpdate -import dev.inmo.tgbotapi.extensions.utils.asShippingQueryUpdate import dev.inmo.tgbotapi.types.payments.PreCheckoutQuery -import dev.inmo.tgbotapi.types.payments.ShippingQuery import dev.inmo.tgbotapi.types.update.abstracts.Update /** diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ShippingQueryTriggers.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ShippingQueryTriggers.kt index 4fcbeab37e..37cb05be12 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ShippingQueryTriggers.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ShippingQueryTriggers.kt @@ -1,10 +1,10 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling import dev.inmo.tgbotapi.extensions.behaviour_builder.* -import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.CallbackQueryFilterByUser import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.ShippingQueryFilterByUser import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter -import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.* +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByUserShippingQueryMarkerFactory +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory import dev.inmo.tgbotapi.extensions.utils.asShippingQueryUpdate import dev.inmo.tgbotapi.types.payments.ShippingQuery import dev.inmo.tgbotapi.types.update.abstracts.Update 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 6f12abd39c..9c72aea0ad 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 @@ -3,6 +3,7 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.utils typealias SimpleFilter = suspend (T) -> Boolean inline fun SimpleFilter(noinline block: SimpleFilter) = block +val TrueSimpleFilter = SimpleFilter { true } /** * @return [SimpleFilter] which will return true in case when all the items in incoming data passed [this] filter diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/handlers_registrar/HandleableCallbackBasedHolder.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/handlers_registrar/HandleableCallbackBasedHolder.kt new file mode 100644 index 0000000000..bf5b87c8e6 --- /dev/null +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/handlers_registrar/HandleableCallbackBasedHolder.kt @@ -0,0 +1,5 @@ +package dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers_registrar + +class HandleableCallbackBasedHolder : HandleableTriggersHolder Boolean>() { + suspend fun isHandled(data: T) = handleable.any { it(data) } +} diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/handlers_registrar/HandleableRegexesHolder.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/handlers_registrar/HandleableRegexesHolder.kt new file mode 100644 index 0000000000..5497d4e0b8 --- /dev/null +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/handlers_registrar/HandleableRegexesHolder.kt @@ -0,0 +1,7 @@ +package dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers_registrar + +class HandleableRegexesHolder : HandleableTriggersHolder() { + fun isHandled(command: String) = handleable.any { + it.matches(command) + } +} diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/handlers_registrar/HandleableTriggersHolder.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/handlers_registrar/HandleableTriggersHolder.kt new file mode 100644 index 0000000000..a182a7eced --- /dev/null +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/handlers_registrar/HandleableTriggersHolder.kt @@ -0,0 +1,27 @@ +package dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers_registrar + +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock + +open class HandleableTriggersHolder( + preset: List = emptyList() +) { + protected val commandsMutex = Mutex() + protected val _handleable = mutableListOf().also { + it.addAll(preset) + } + val handleable: List + get() = _handleable.toList() + + suspend fun registerHandleable(data: T) { + commandsMutex.withLock { + _handleable.add(data) + } + } + + suspend fun unregisterHandleable(data: T) { + commandsMutex.withLock { + _handleable.remove(data) + } + } +} diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/handlers_registrar/TriggersRegistrar.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/handlers_registrar/TriggersRegistrar.kt new file mode 100644 index 0000000000..4c907915fd --- /dev/null +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/handlers_registrar/TriggersRegistrar.kt @@ -0,0 +1,8 @@ +package dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers_registrar + +import dev.inmo.tgbotapi.types.CallbackQuery.DataCallbackQuery + +class TriggersHolder { + val handleableCommandsHolder = HandleableRegexesHolder() + val handleableCallbackQueriesDataHolder = HandleableCallbackBasedHolder() +}