From c09d089707cd81b075306faaccdcc23259bbfbae Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sun, 10 Aug 2025 18:05:48 +0600 Subject: [PATCH] add lazy loadable bot info --- .../api/tgbotapi.behaviour_builder.fsm.api | 24 ++--- .../BehaviourContextWithFSMBuilder.kt | 11 +- .../behaviour_builder/TelegramBotWithFSM.kt | 4 + .../api/tgbotapi.behaviour_builder.api | 46 +++++--- .../behaviour_builder/BehaviourBuilders.kt | 10 +- .../behaviour_builder/BehaviourContext.kt | 20 +++- .../behaviour_builder/TelegramBot.kt | 4 + ...ltCustomBehaviourContextAndTypeReceiver.kt | 102 ++++++++++++++++++ 8 files changed, 192 insertions(+), 29 deletions(-) create mode 100644 tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/DefaultCustomBehaviourContextAndTypeReceiver.kt diff --git a/tgbotapi.behaviour_builder.fsm/api/tgbotapi.behaviour_builder.fsm.api b/tgbotapi.behaviour_builder.fsm/api/tgbotapi.behaviour_builder.fsm.api index 38e3f6f5cb..bfebf44c5f 100644 --- a/tgbotapi.behaviour_builder.fsm/api/tgbotapi.behaviour_builder.fsm.api +++ b/tgbotapi.behaviour_builder.fsm/api/tgbotapi.behaviour_builder.fsm.api @@ -35,14 +35,14 @@ public final class dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourConte } public final class dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContextWithFSMBuilderKt { - public static final fun buildBehaviourWithFSM (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun buildBehaviourWithFSM (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/flow/Flow;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun buildBehaviourWithFSM$default (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static synthetic fun buildBehaviourWithFSM$default (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/flow/Flow;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun buildBehaviourWithFSMAndStartLongPolling (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;Lkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun buildBehaviourWithFSMAndStartLongPolling (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/flow/Flow;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;Lkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun buildBehaviourWithFSMAndStartLongPolling$default (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;Lkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static synthetic fun buildBehaviourWithFSMAndStartLongPolling$default (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/flow/Flow;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;Lkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static final fun buildBehaviourWithFSM (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;ZLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun buildBehaviourWithFSM (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/flow/Flow;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;ZLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun buildBehaviourWithFSM$default (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;ZLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static synthetic fun buildBehaviourWithFSM$default (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/flow/Flow;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;ZLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static final fun buildBehaviourWithFSMAndStartLongPolling (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;Lkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;ZLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun buildBehaviourWithFSMAndStartLongPolling (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/flow/Flow;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;Lkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;ZLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun buildBehaviourWithFSMAndStartLongPolling$default (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;Lkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;ZLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static synthetic fun buildBehaviourWithFSMAndStartLongPolling$default (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/flow/Flow;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;Lkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;ZLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; } public final class dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContextWithFSMKt { @@ -128,9 +128,9 @@ public final class dev/inmo/tgbotapi/extensions/behaviour_builder/DefaultBehavio } public final class dev/inmo/tgbotapi/extensions/behaviour_builder/TelegramBotWithFSMKt { - public static final fun telegramBotWithBehaviourAndFSM (Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;ZLkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun telegramBotWithBehaviourAndFSM$default (Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;ZLkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun telegramBotWithBehaviourAndFSMAndStartLongPolling (Ljava/lang/String;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;ZLkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun telegramBotWithBehaviourAndFSMAndStartLongPolling$default (Ljava/lang/String;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;ZLkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static final fun telegramBotWithBehaviourAndFSM (Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;ZLkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun telegramBotWithBehaviourAndFSM$default (Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;ZLkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static final fun telegramBotWithBehaviourAndFSMAndStartLongPolling (Ljava/lang/String;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;ZLkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun telegramBotWithBehaviourAndFSMAndStartLongPolling$default (Ljava/lang/String;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Ldev/inmo/micro_utils/fsm/common/StatesManager;Ljava/util/List;Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourWithFSMStateHandlerHolder;ZLkotlin/jvm/functions/Function3;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; } diff --git a/tgbotapi.behaviour_builder.fsm/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContextWithFSMBuilder.kt b/tgbotapi.behaviour_builder.fsm/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContextWithFSMBuilder.kt index 4718da736b..3a17d1bc3c 100644 --- a/tgbotapi.behaviour_builder.fsm/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContextWithFSMBuilder.kt +++ b/tgbotapi.behaviour_builder.fsm/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContextWithFSMBuilder.kt @@ -7,6 +7,7 @@ import dev.inmo.micro_utils.fsm.common.managers.InMemoryDefaultStatesManagerRepo import dev.inmo.micro_utils.fsm.common.utils.StateHandlingErrorHandler import dev.inmo.micro_utils.fsm.common.utils.defaultStateHandlingErrorHandler import dev.inmo.tgbotapi.bot.TelegramBot +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.optionallyWithDefaultReceiver import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.longPolling import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.updateHandlerWithMediaGroupsAdaptation import dev.inmo.tgbotapi.types.Seconds @@ -35,13 +36,14 @@ suspend fun TelegramBot.buildBehaviourWithFSM( onStateHandlingErrorHandler: StateHandlingErrorHandler = defaultStateHandlingErrorHandler(), subcontextInitialAction: CustomBehaviourContextAndTypeReceiver = {}, stateInitialAction: CustomBehaviourContextAndTypeReceiver, Unit, T> = {}, + useDefaultSubcontextInitialAction: Boolean = true, block: CustomBehaviourContextReceiver, Unit> ): DefaultBehaviourContextWithFSM = BehaviourContextWithFSM( behaviourContext = DefaultBehaviourContext( bot = this, scope = defaultExceptionsHandler ?.let { scope + ContextSafelyExceptionHandler(it) } ?: scope, upstreamUpdatesFlow = upstreamUpdatesFlow, - subcontextInitialAction = subcontextInitialAction + subcontextInitialAction = subcontextInitialAction.optionallyWithDefaultReceiver(useDefaultSubcontextInitialAction) ), handlers = presetHandlers, statesManager = statesManager, @@ -73,6 +75,7 @@ suspend fun TelegramBot.buildBehaviourWithFSMAndStartLongPolling( mediaGroupsDebounceTimeMillis: Long? = 1000L, subcontextInitialAction: CustomBehaviourContextAndTypeReceiver = {}, stateInitialAction: CustomBehaviourContextAndTypeReceiver, Unit, T> = {}, + useDefaultSubcontextInitialAction: Boolean = true, block: CustomBehaviourContextReceiver, Unit> ): Pair, Job> = buildBehaviourWithFSM( upstreamUpdatesFlow = upstreamUpdatesFlow, @@ -84,6 +87,7 @@ suspend fun TelegramBot.buildBehaviourWithFSMAndStartLongPolling( onStateHandlingErrorHandler = onStateHandlingErrorHandler, subcontextInitialAction = subcontextInitialAction, stateInitialAction = stateInitialAction, + useDefaultSubcontextInitialAction = useDefaultSubcontextInitialAction, block = block ).run { this to scope.launch { @@ -120,13 +124,14 @@ suspend fun TelegramBot.buildBehaviourWithFSM( onStateHandlingErrorHandler: StateHandlingErrorHandler = defaultStateHandlingErrorHandler(), subcontextInitialAction: CustomBehaviourContextAndTypeReceiver = {}, stateInitialAction: CustomBehaviourContextAndTypeReceiver, Unit, T> = {}, + useDefaultSubcontextInitialAction: Boolean = true, block: CustomBehaviourContextReceiver, Unit> ): DefaultBehaviourContextWithFSM = BehaviourContextWithFSM( DefaultBehaviourContext( this, defaultExceptionsHandler ?.let { scope + ContextSafelyExceptionHandler(it) } ?: scope, upstreamUpdatesFlow = flowUpdatesFilter.allUpdatesFlow, - subcontextInitialAction = subcontextInitialAction + subcontextInitialAction = subcontextInitialAction.optionallyWithDefaultReceiver(useDefaultSubcontextInitialAction) ), presetHandlers, statesManager, @@ -163,6 +168,7 @@ suspend fun TelegramBot.buildBehaviourWithFSMAndStartLongPolling( mediaGroupsDebounceTimeMillis: Long? = 1000L, subcontextInitialAction: CustomBehaviourContextAndTypeReceiver = {}, stateInitialAction: CustomBehaviourContextAndTypeReceiver, Unit, T> = {}, + useDefaultSubcontextInitialAction: Boolean = true, block: CustomBehaviourContextReceiver, Unit> ) = FlowsUpdatesFilter().let { buildBehaviourWithFSM( @@ -175,6 +181,7 @@ suspend fun TelegramBot.buildBehaviourWithFSMAndStartLongPolling( onStateHandlingErrorHandler = onStateHandlingErrorHandler, subcontextInitialAction = subcontextInitialAction, stateInitialAction = stateInitialAction, + useDefaultSubcontextInitialAction = useDefaultSubcontextInitialAction, block = block ).run { start() diff --git a/tgbotapi.behaviour_builder.fsm/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/TelegramBotWithFSM.kt b/tgbotapi.behaviour_builder.fsm/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/TelegramBotWithFSM.kt index 2b38cb12e1..61a7817e01 100644 --- a/tgbotapi.behaviour_builder.fsm/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/TelegramBotWithFSM.kt +++ b/tgbotapi.behaviour_builder.fsm/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/TelegramBotWithFSM.kt @@ -58,6 +58,7 @@ suspend fun telegramBotWithBehaviourAndFSM( subcontextInitialAction: CustomBehaviourContextAndTypeReceiver = {}, stateInitialAction: CustomBehaviourContextAndTypeReceiver, Unit, T> = {}, fileLinkUrlMapper: TelegramAPIUrlsKeeper.(String) -> String = { "${fileBaseUrl}/$it" }, + useDefaultSubcontextInitialAction: Boolean = true, block: CustomBehaviourContextReceiver, Unit> ): TelegramBot = telegramBot( token, @@ -80,6 +81,7 @@ suspend fun telegramBotWithBehaviourAndFSM( mediaGroupsDebounceTimeMillis = mediaGroupsDebounceTimeMillis, subcontextInitialAction = subcontextInitialAction, stateInitialAction = stateInitialAction, + useDefaultSubcontextInitialAction = useDefaultSubcontextInitialAction, block = block ) } @@ -117,6 +119,7 @@ suspend fun telegramBotWithBehaviourAndFSMAndStartLongPolling( subcontextInitialAction: CustomBehaviourContextAndTypeReceiver = {}, stateInitialAction: CustomBehaviourContextAndTypeReceiver, Unit, T> = {}, fileLinkUrlMapper: TelegramAPIUrlsKeeper.(String) -> String = { "${fileBaseUrl}/$it" }, + useDefaultSubcontextInitialAction: Boolean = true, block: CustomBehaviourContextReceiver, Unit> ): Pair { return telegramBot( @@ -139,6 +142,7 @@ suspend fun telegramBotWithBehaviourAndFSMAndStartLongPolling( mediaGroupsDebounceTimeMillis = mediaGroupsDebounceTimeMillis, subcontextInitialAction = subcontextInitialAction, stateInitialAction = stateInitialAction, + useDefaultSubcontextInitialAction = useDefaultSubcontextInitialAction, block = block ) } diff --git a/tgbotapi.behaviour_builder/api/tgbotapi.behaviour_builder.api b/tgbotapi.behaviour_builder/api/tgbotapi.behaviour_builder.api index 96bd4fad6c..7e79fb02ca 100644 --- a/tgbotapi.behaviour_builder/api/tgbotapi.behaviour_builder.api +++ b/tgbotapi.behaviour_builder/api/tgbotapi.behaviour_builder.api @@ -1,8 +1,8 @@ public final class dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourBuildersKt { - public static final fun buildBehaviour (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun buildBehaviour$default (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun buildBehaviourWithLongPolling (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun buildBehaviourWithLongPolling$default (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static final fun buildBehaviour (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;ZLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun buildBehaviour$default (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;ZLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static final fun buildBehaviourWithLongPolling (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;ZLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun buildBehaviourWithLongPolling$default (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function2;IZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;ZLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; } public abstract interface class dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContext : dev/inmo/tgbotapi/bot/RequestsExecutor, dev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter, kotlinx/coroutines/CoroutineScope { @@ -64,13 +64,14 @@ public final class dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourConte } public final class dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContextKt { - public static final fun BehaviourContext (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/CoroutineScope;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Ldev/inmo/tgbotapi/extensions/behaviour_builder/utils/handlers_registrar/TriggersHolder;Lkotlin/jvm/functions/Function3;)Ldev/inmo/tgbotapi/extensions/behaviour_builder/DefaultBehaviourContext; - public static final fun BehaviourContext (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/CoroutineScope;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Ldev/inmo/tgbotapi/extensions/behaviour_builder/utils/handlers_registrar/TriggersHolder;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static synthetic fun BehaviourContext$default (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/CoroutineScope;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Ldev/inmo/tgbotapi/extensions/behaviour_builder/utils/handlers_registrar/TriggersHolder;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Ldev/inmo/tgbotapi/extensions/behaviour_builder/DefaultBehaviourContext; - public static synthetic fun BehaviourContext$default (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/CoroutineScope;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Ldev/inmo/tgbotapi/extensions/behaviour_builder/utils/handlers_registrar/TriggersHolder;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/Object; + public static final fun BehaviourContext (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/CoroutineScope;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Ldev/inmo/tgbotapi/extensions/behaviour_builder/utils/handlers_registrar/TriggersHolder;Lkotlin/jvm/functions/Function3;ZLkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public static final fun BehaviourContext (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/CoroutineScope;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Ldev/inmo/tgbotapi/extensions/behaviour_builder/utils/handlers_registrar/TriggersHolder;ZLkotlin/jvm/functions/Function3;)Ldev/inmo/tgbotapi/extensions/behaviour_builder/DefaultBehaviourContext; + public static synthetic fun BehaviourContext$default (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/CoroutineScope;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Ldev/inmo/tgbotapi/extensions/behaviour_builder/utils/handlers_registrar/TriggersHolder;Lkotlin/jvm/functions/Function3;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/Object; + public static synthetic fun BehaviourContext$default (Ldev/inmo/tgbotapi/bot/RequestsExecutor;Lkotlinx/coroutines/CoroutineScope;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Ldev/inmo/tgbotapi/extensions/behaviour_builder/utils/handlers_registrar/TriggersHolder;ZLkotlin/jvm/functions/Function3;ILjava/lang/Object;)Ldev/inmo/tgbotapi/extensions/behaviour_builder/DefaultBehaviourContext; public static final fun BehaviourContextAndTwoTypesReceiver (Lkotlin/jvm/functions/Function4;)Lkotlin/jvm/functions/Function4; public static final fun BehaviourContextAndTypeReceiver (Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function3; public static final fun BehaviourContextReceiver (Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function2; + public static final fun CustomBehaviourContextAndTypeReceiver (Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function3; public static final fun CustomBehaviourContextReceiver (Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function2; public static final fun createSubContext (Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContext;Lkotlinx/coroutines/CoroutineScope;Ldev/inmo/tgbotapi/extensions/behaviour_builder/utils/handlers_registrar/TriggersHolder;Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function3;)Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContext; public static synthetic fun createSubContext$default (Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContext;Lkotlinx/coroutines/CoroutineScope;Ldev/inmo/tgbotapi/extensions/behaviour_builder/utils/handlers_registrar/TriggersHolder;Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContext; @@ -134,10 +135,10 @@ public final class dev/inmo/tgbotapi/extensions/behaviour_builder/DefaultCorouti } public final class dev/inmo/tgbotapi/extensions/behaviour_builder/TelegramBotKt { - public static final fun telegramBotWithBehaviour (Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun telegramBotWithBehaviour$default (Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun telegramBotWithBehaviourAndLongPolling (Ljava/lang/String;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ZIZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun telegramBotWithBehaviourAndLongPolling$default (Ljava/lang/String;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ZIZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static final fun telegramBotWithBehaviour (Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun telegramBotWithBehaviour$default (Ljava/lang/String;Ldev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static final fun telegramBotWithBehaviourAndLongPolling (Ljava/lang/String;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ZIZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun telegramBotWithBehaviourAndLongPolling$default (Ljava/lang/String;Lkotlinx/coroutines/CoroutineScope;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ZIZZLjava/lang/Long;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; } public final class dev/inmo/tgbotapi/extensions/behaviour_builder/VariantsKt { @@ -1587,6 +1588,27 @@ public final class dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handl public static synthetic fun onShippingQuery$default (Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContext;Ldev/inmo/tgbotapi/extensions/behaviour_builder/utils/SimpleFilter;Lkotlin/jvm/functions/Function4;Ldev/inmo/tgbotapi/extensions/behaviour_builder/utils/marker_factories/MarkerFactory;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lkotlinx/coroutines/Job; } +public final class dev/inmo/tgbotapi/extensions/behaviour_builder/utils/DefaultCustomBehaviourContextAndTypeReceiver : kotlin/coroutines/jvm/internal/SuspendFunction, kotlin/jvm/functions/Function3 { + public static final field BOT_INFO_RECEIVER Ljava/lang/String; + public static final field Companion Ldev/inmo/tgbotapi/extensions/behaviour_builder/utils/DefaultCustomBehaviourContextAndTypeReceiver$Companion; + public fun (Lkotlin/jvm/functions/Function3;)V + public fun invoke (Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContext;Ldev/inmo/tgbotapi/types/update/abstracts/Update;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public synthetic fun invoke (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +} + +public final class dev/inmo/tgbotapi/extensions/behaviour_builder/utils/DefaultCustomBehaviourContextAndTypeReceiver$Companion { +} + +public abstract interface class dev/inmo/tgbotapi/extensions/behaviour_builder/utils/DefaultCustomBehaviourContextAndTypeReceiver$IReceiver { + public abstract fun invoke (Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +} + +public final class dev/inmo/tgbotapi/extensions/behaviour_builder/utils/DefaultCustomBehaviourContextAndTypeReceiverKt { + public static final fun botInfo (Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun optionallyWithDefaultReceiver (Lkotlin/jvm/functions/Function3;Z)Lkotlin/jvm/functions/Function3; + public static final fun withDefaultReceiver (Lkotlin/jvm/functions/Function3;)Ldev/inmo/tgbotapi/extensions/behaviour_builder/utils/DefaultCustomBehaviourContextAndTypeReceiver; +} + public final class dev/inmo/tgbotapi/extensions/behaviour_builder/utils/LiveLocationKt { public static final fun followLocation (Ldev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContext;Ldev/inmo/tgbotapi/types/message/abstracts/ContentMessage;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourBuilders.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourBuilders.kt index eea57b0afd..b2f7bc2179 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourBuilders.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourBuilders.kt @@ -3,6 +3,7 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder import dev.inmo.micro_utils.coroutines.ContextSafelyExceptionHandler import dev.inmo.micro_utils.coroutines.ExceptionHandler import dev.inmo.tgbotapi.bot.TelegramBot +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.DefaultCustomBehaviourContextAndTypeReceiver import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.longPolling import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.startGettingOfUpdatesByLongPolling import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.updateHandlerWithMediaGroupsAdaptation @@ -31,6 +32,7 @@ suspend fun TelegramBot.buildBehaviour( scope: CoroutineScope = defaultCoroutineScopeProvider(), defaultExceptionsHandler: ExceptionHandler? = null, subcontextInitialAction: CustomBehaviourContextAndTypeReceiver = {}, + useDefaultSubcontextInitialAction: Boolean = true, block: BehaviourContextReceiver ): BehaviourContext = BehaviourContext( bot = this, @@ -42,7 +44,11 @@ suspend fun TelegramBot.buildBehaviour( } }, flowsUpdatesFilter = flowUpdatesFilter, - subcontextInitialAction = subcontextInitialAction + subcontextInitialAction = if (useDefaultSubcontextInitialAction) { + DefaultCustomBehaviourContextAndTypeReceiver(subcontextInitialAction) + } else { + subcontextInitialAction + } ).apply { block() } @@ -67,12 +73,14 @@ suspend fun TelegramBot.buildBehaviourWithLongPolling( autoSkipTimeoutExceptions: Boolean = true, mediaGroupsDebounceTimeMillis: Long? = 1000L, subcontextInitialAction: CustomBehaviourContextAndTypeReceiver = {}, + useDefaultSubcontextInitialAction: Boolean = true, block: BehaviourContextReceiver ): Job { val behaviourContext = buildBehaviour( scope = scope, defaultExceptionsHandler = defaultExceptionsHandler, subcontextInitialAction = subcontextInitialAction, + useDefaultSubcontextInitialAction = useDefaultSubcontextInitialAction, block = block ) return longPolling( 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 03fc71c64d..84bb692db1 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 @@ -6,6 +6,7 @@ import dev.inmo.kslog.common.KSLog 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.extensions.behaviour_builder.utils.optionallyWithDefaultReceiver import dev.inmo.tgbotapi.types.UpdateId import dev.inmo.tgbotapi.types.update.abstracts.Update import dev.inmo.tgbotapi.updateshandlers.* @@ -24,6 +25,7 @@ typealias CustomBehaviourContextAndTwoTypesReceiver = suspend BC. typealias BehaviourContextAndTwoTypesReceiver = CustomBehaviourContextAndTwoTypesReceiver inline fun BehaviourContextReceiver(noinline block: BehaviourContextReceiver) = block inline fun CustomBehaviourContextReceiver(noinline block: CustomBehaviourContextReceiver) = block +inline fun CustomBehaviourContextAndTypeReceiver(noinline block: CustomBehaviourContextAndTypeReceiver) = block inline fun BehaviourContextAndTypeReceiver(noinline block: BehaviourContextAndTypeReceiver) = block inline fun BehaviourContextAndTwoTypesReceiver(noinline block: BehaviourContextAndTwoTypesReceiver) = block internal inline fun CustomBehaviourContextAndTwoTypesReceiver.toOneType( @@ -134,8 +136,15 @@ fun BehaviourContext( scope: CoroutineScope, flowsUpdatesFilter: FlowsUpdatesFilter = FlowsUpdatesFilter(), triggersHolder: TriggersHolder = TriggersHolder(), + useDefaultSubcontextInitialAction: Boolean = true, subcontextInitialAction: CustomBehaviourContextAndTypeReceiver = {} -) = DefaultBehaviourContext(bot, scope, upstreamUpdatesFlow = flowsUpdatesFilter.allUpdatesFlow, triggersHolder = triggersHolder, subcontextInitialAction = subcontextInitialAction) +) = DefaultBehaviourContext( + bot = bot, + scope = scope, + upstreamUpdatesFlow = flowsUpdatesFilter.allUpdatesFlow, + triggersHolder = triggersHolder, + subcontextInitialAction = subcontextInitialAction.optionallyWithDefaultReceiver(useDefaultSubcontextInitialAction) +) inline fun BehaviourContext( bot: TelegramBot, @@ -143,8 +152,15 @@ inline fun BehaviourContext( flowsUpdatesFilter: FlowsUpdatesFilter = FlowsUpdatesFilter(), triggersHolder: TriggersHolder = TriggersHolder(), noinline subcontextInitialAction: CustomBehaviourContextAndTypeReceiver = {}, + useDefaultSubcontextInitialAction: Boolean = true, crossinline block: BehaviourContext.() -> T -) = DefaultBehaviourContext(bot, scope, upstreamUpdatesFlow = flowsUpdatesFilter.allUpdatesFlow, triggersHolder = triggersHolder, subcontextInitialAction = subcontextInitialAction).run(block) +) = DefaultBehaviourContext( + bot = bot, + scope = scope, + upstreamUpdatesFlow = flowsUpdatesFilter.allUpdatesFlow, + triggersHolder = triggersHolder, + subcontextInitialAction = subcontextInitialAction.optionallyWithDefaultReceiver(useDefaultSubcontextInitialAction) +).run(block) /** * Creates new [BehaviourContext] using its [BehaviourContext.copy] method diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/TelegramBot.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/TelegramBot.kt index d4f0afc3d6..6cc62eaaa8 100644 --- a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/TelegramBot.kt +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/TelegramBot.kt @@ -39,6 +39,7 @@ suspend fun telegramBotWithBehaviour( testServer: Boolean = false, subcontextInitialAction: CustomBehaviourContextAndTypeReceiver = {}, fileLinkUrlMapper: TelegramAPIUrlsKeeper.(String) -> String = { "${fileBaseUrl}/$it" }, + useDefaultSubcontextInitialAction: Boolean = true, block: BehaviourContextReceiver ): TelegramBot = telegramBot( token, @@ -52,6 +53,7 @@ suspend fun telegramBotWithBehaviour( scope = scope ?: CoroutineScope(coroutineContext), defaultExceptionsHandler = defaultExceptionsHandler, subcontextInitialAction = subcontextInitialAction, + useDefaultSubcontextInitialAction = useDefaultSubcontextInitialAction, block = block ) } @@ -86,6 +88,7 @@ suspend fun telegramBotWithBehaviourAndLongPolling( mediaGroupsDebounceTimeMillis: Long? = 1000L, subcontextInitialAction: CustomBehaviourContextAndTypeReceiver = {}, fileLinkUrlMapper: TelegramAPIUrlsKeeper.(String) -> String = { "${fileBaseUrl}/$it" }, + useDefaultSubcontextInitialAction: Boolean = true, block: BehaviourContextReceiver ): Pair { return telegramBot( @@ -103,6 +106,7 @@ suspend fun telegramBotWithBehaviourAndLongPolling( autoSkipTimeoutExceptions = autoSkipTimeoutExceptions, mediaGroupsDebounceTimeMillis = mediaGroupsDebounceTimeMillis, subcontextInitialAction = subcontextInitialAction, + useDefaultSubcontextInitialAction = useDefaultSubcontextInitialAction, block = block ) } diff --git a/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/DefaultCustomBehaviourContextAndTypeReceiver.kt b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/DefaultCustomBehaviourContextAndTypeReceiver.kt new file mode 100644 index 0000000000..fd09aa9cae --- /dev/null +++ b/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/DefaultCustomBehaviourContextAndTypeReceiver.kt @@ -0,0 +1,102 @@ +package dev.inmo.tgbotapi.extensions.behaviour_builder.utils + +import dev.inmo.micro_utils.common.Warning +import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext +import dev.inmo.tgbotapi.extensions.behaviour_builder.CustomBehaviourContextAndTypeReceiver +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.DefaultCustomBehaviourContextAndTypeReceiver.Companion.BOT_INFO_RECEIVER +import dev.inmo.tgbotapi.requests.bot.GetMe +import dev.inmo.tgbotapi.types.chat.ExtendedBot +import dev.inmo.tgbotapi.types.update.abstracts.Update +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock + +/** + * Returns bot information (result of [GetMe]) associated with this [BehaviourContext], if available. + * + * The value is lazily computed and cached by [DefaultCustomBehaviourContextAndTypeReceiver] when it is used + * to wrap behaviour handlers. If this context was not prepared by that wrapper, the function returns null. + * + * Thread-safety: + * - The underlying retrieval is protected by a mutex to ensure the info is fetched at most once per context. + * + * @return [ExtendedBot] with bot details, or null if no bot info provider is registered in this context. + */ +suspend fun BehaviourContext.botInfo(): ExtendedBot? { + return (data[BOT_INFO_RECEIVER] as? DefaultCustomBehaviourContextAndTypeReceiver.IReceiver) ?.run { + invoke() + } +} + +@Warning("It is internal API and can be changed without notes") +fun CustomBehaviourContextAndTypeReceiver.withDefaultReceiver() = DefaultCustomBehaviourContextAndTypeReceiver(this) +@Warning("It is internal API and can be changed without notes") +fun CustomBehaviourContextAndTypeReceiver.optionallyWithDefaultReceiver( + include: Boolean +) = if (include) { + withDefaultReceiver() +} else { + this +} + +/** + * Behaviour wrapper that injects a lazily-evaluated, cached provider of bot information into the [BehaviourContext]. + * + * When this wrapper is used, any code executed inside it may call [BehaviourContext.botInfo] to obtain + * the current bot's [ExtendedBot] information. The info is fetched via [GetMe] only once and then cached + * for subsequent calls, with concurrent access synchronized by a mutex. + * + * @param BC Type of [BehaviourContext] used in the wrapped logic. + * @param R Result type produced by the wrapped receiver. + * @param U Type of [Update] handled by the wrapped receiver. + * @param wrapperReceiver The original receiver to be invoked after the bot info provider is registered in the context. + */ +class DefaultCustomBehaviourContextAndTypeReceiver( + private val wrapperReceiver: CustomBehaviourContextAndTypeReceiver +) : CustomBehaviourContextAndTypeReceiver { + private var botInfo: ExtendedBot? = null + private val mutex = Mutex() + + /** + * Lightweight provider of bot information bound to a [BehaviourContext]. + * + * Implementations must return the current [ExtendedBot] instance, computing it if necessary. + */ + fun interface IReceiver { + /** + * Get or compute the bot information for the current [BehaviourContext]. + * + * Implementations may cache the value and are free to apply synchronization as needed. + */ + suspend fun BehaviourContext.invoke(): ExtendedBot + } + + /** + * Internal provider that performs a single, thread-safe retrieval of bot info via [GetMe] and caches it. + */ + private val internalReceiver: IReceiver = IReceiver { + botInfo ?: mutex.withLock { + botInfo ?: execute(GetMe).also { + botInfo = it + } + } + } + + /** + * Registers the internal bot info provider in [BehaviourContext.data] and then delegates to [wrapperReceiver]. + * + * The provider is stored under [BOT_INFO_RECEIVER] key, enabling calls to [BehaviourContext.botInfo] within + * the wrapped behaviour. + */ + override suspend fun invoke(p1: BC, p2: U): R { + p1.data[BOT_INFO_RECEIVER] = internalReceiver + + return wrapperReceiver(p1, p2) + } + + companion object { + /** + * Key used to store the bot info provider inside [BehaviourContext.data]. + */ + const val BOT_INFO_RECEIVER = "ktgbotapi_bot_info_receiver" + } +} \ No newline at end of file