From 27a24a18a689792f0f9b0f5d5df7b178ba1fb8f0 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sat, 21 May 2022 21:44:27 +0600 Subject: [PATCH] fix of updates funnel in subsequent behaviour contexts --- .../behaviour_builder/BehaviourContext.kt | 79 +++++++++++++------ .../expectations/WaitCallbackQuery.kt | 4 +- .../triggers_handling/MainTrigger.kt | 11 +-- 3 files changed, 65 insertions(+), 29 deletions(-) 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 4621e6e242..a1c5173def 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 @@ -49,6 +49,19 @@ interface BehaviourContext : FlowsUpdatesFilter, TelegramBot, CoroutineScope { 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() + ): BehaviourContext + + /** + * @param updatesFilter unused + */ + @Deprecated("Do not use this method") fun copy( bot: TelegramBot = this.bot, scope: CoroutineScope = this.scope, @@ -57,7 +70,7 @@ interface BehaviourContext : FlowsUpdatesFilter, TelegramBot, CoroutineScope { upstreamUpdatesFlow: Flow? = null, triggersHolder: TriggersHolder = TriggersHolder(), updatesFilter: BehaviourContextAndTypeReceiver? = null - ): BehaviourContext + ): BehaviourContext = copy(bot, scope, broadcastChannelsSize, onBufferOverflow, upstreamUpdatesFlow, triggersHolder) } class DefaultBehaviourContext( @@ -67,6 +80,7 @@ class DefaultBehaviourContext( onBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND, private val upstreamUpdatesFlow: Flow? = null, override val triggersHolder: TriggersHolder = TriggersHolder(), + @Deprecated("This method is not used anymore") private val updatesFilter: BehaviourContextAndTypeReceiver? = null ) : AbstractFlowsUpdatesFilter(), TelegramBot by bot, CoroutineScope by scope, BehaviourContext { @@ -80,13 +94,6 @@ class DefaultBehaviourContext( } else { it } - }.let { - val updatesFilter = updatesFilter - if (updatesFilter != null) { - it.filter { updatesFilter(it) } - } else { - it - } }.accumulatorFlow(scope) override val asUpdateReceiver: UpdateReceiver = additionalUpdatesSharedFlow::emit @@ -96,9 +103,8 @@ class DefaultBehaviourContext( broadcastChannelsSize: Int, onBufferOverflow: BufferOverflow, upstreamUpdatesFlow: Flow?, - triggersHolder: TriggersHolder, - updatesFilter: BehaviourContextAndTypeReceiver? - ): DefaultBehaviourContext = DefaultBehaviourContext(bot, scope, broadcastChannelsSize, onBufferOverflow, upstreamUpdatesFlow, triggersHolder, updatesFilter) + triggersHolder: TriggersHolder + ): DefaultBehaviourContext = DefaultBehaviourContext(bot, scope, broadcastChannelsSize, onBufferOverflow, upstreamUpdatesFlow, triggersHolder) } fun BehaviourContext( @@ -116,24 +122,34 @@ inline fun BehaviourContext( crossinline block: BehaviourContext.() -> T ) = DefaultBehaviourContext(bot, scope, upstreamUpdatesFlow = flowsUpdatesFilter.allUpdatesFlow, triggersHolder = triggersHolder).run(block) +/** + * Creates new [BehaviourContext] using its [BehaviourContext.copy] method + * + * @param updatesFilter This param will not be used anymore + */ fun BC.createSubContext( scope: CoroutineScope = LinkedSupervisorScope(), triggersHolder: TriggersHolder = this.triggersHolder, updatesUpstreamFlow: Flow = allUpdatesFlow, - updatesFilter: CustomBehaviourContextAndTypeReceiver? = null, ) = copy( scope = scope, - updatesFilter = updatesFilter ?.let { _ -> - { - (this as? BC) ?.run { - updatesFilter(it) - } ?: true - } - }, upstreamUpdatesFlow = updatesUpstreamFlow, triggersHolder = triggersHolder ) as BC +/** + * Creates new [BehaviourContext] using its [BehaviourContext.copy] method + * + * @param updatesFilter This param will not be used anymore + */ +@Deprecated("It is not recommended to use updates filter anymore") +fun BC.createSubContext( + scope: CoroutineScope = LinkedSupervisorScope(), + triggersHolder: TriggersHolder = this.triggersHolder, + updatesUpstreamFlow: Flow = allUpdatesFlow, + updatesFilter: CustomBehaviourContextAndTypeReceiver?, +) = createSubContext(scope, triggersHolder, updatesUpstreamFlow) + /** * Launch [behaviourContextReceiver] in context of [this] as [BehaviourContext] and as [kotlin.coroutines.CoroutineContext] * @@ -158,21 +174,40 @@ suspend fun BC.createSubContextAndDoWithUpdatesFilter scope: CoroutineScope = LinkedSupervisorScope(), triggersHolder: TriggersHolder = this.triggersHolder, updatesUpstreamFlow: Flow = allUpdatesFlow, - updatesFilter: CustomBehaviourContextAndTypeReceiver? = null, stopOnCompletion: Boolean = true, behaviourContextReceiver: CustomBehaviourContextReceiver ): T { return createSubContext( scope, triggersHolder, - updatesUpstreamFlow, - updatesFilter + updatesUpstreamFlow ).doInContext( stopOnCompletion, behaviourContextReceiver ) } +/** + * Creates new one [BehaviourContext] using [createSubContext] and launches [behaviourContextReceiver] in a new context + * using [doInContext] + * + * @param stopOnCompletion ___TRUE BY DEFAULT___ + * @param updatesFilter Is not used anymore + */ +@Deprecated("It is not recommended to use updates filter anymore") +suspend fun BC.createSubContextAndDoWithUpdatesFilter( + scope: CoroutineScope = LinkedSupervisorScope(), + triggersHolder: TriggersHolder = this.triggersHolder, + updatesUpstreamFlow: Flow = allUpdatesFlow, + updatesFilter: CustomBehaviourContextAndTypeReceiver?, + stopOnCompletion: Boolean = true, + behaviourContextReceiver: CustomBehaviourContextReceiver +): T { + return createSubContextAndDoWithUpdatesFilter( + scope, triggersHolder, updatesUpstreamFlow, stopOnCompletion, behaviourContextReceiver + ) +} + /** * Creates new one [BehaviourContext] using [createSubContext] and launches [behaviourContextReceiver] in a new context * using [doInContext] diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitCallbackQuery.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitCallbackQuery.kt index 2c51e9ef2f..eaa15da352 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitCallbackQuery.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitCallbackQuery.kt @@ -22,8 +22,8 @@ private suspend fun BehaviourContext.waitCallbackQueries( count, errorFactory ) { - val data = it.asCallbackQueryUpdate() ?.data - if (data != null && (filter == null || filter(data))) { + val data = it.asCallbackQueryUpdate() ?.data ?: return@expectFlow emptyList() + if (filter == null || filter(data)) { data.mapper().let(::listOfNotNull) } else { emptyList() diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/MainTrigger.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/MainTrigger.kt index 766972a57b..108465b116 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/MainTrigger.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/MainTrigger.kt @@ -15,16 +15,17 @@ internal suspend inline fun BC.on( noinline updateToData: (Update) -> List? ) = flowsUpdatesFilter.expectFlow(bot) { updateToData(it) ?.mapNotNull { data -> - if (initialFilter ?.invoke(data) != false) data else null + if (initialFilter ?.invoke(data) != false) it to data else null } ?: emptyList() }.subscribeSafelyWithoutExceptionsAsync( scope, - markerFactory::invoke -) { triggerData -> + { markerFactory(it.second) } +) { (update, triggerData) -> createSubContextAndDoWithUpdatesFilter( - updatesFilter = subcontextUpdatesFilter ?.toOneType(triggerData), stopOnCompletion = false ) { - scenarioReceiver(triggerData) + if (subcontextUpdatesFilter ?.invoke(this, triggerData, update) != false) { + scenarioReceiver(triggerData) + } } }