1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2024-11-26 03:58:44 +00:00

several actualizations for behaviour builder with fsm

This commit is contained in:
InsanusMokrassar 2021-10-15 16:28:17 +06:00
parent ad9bc36f8c
commit 179a724d20
3 changed files with 182 additions and 6 deletions

View File

@ -21,6 +21,8 @@ private suspend fun <I : State> BehaviourContextWithFSM.launchStateHandling(
}
interface BehaviourContextWithFSM : BehaviourContext, StatesMachine {
suspend fun start() = start(this)
override fun copy(
bot: TelegramBot,
scope: CoroutineScope,

View File

@ -1,14 +1,18 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder
import dev.inmo.micro_utils.coroutines.ContextSafelyExceptionHandler
import dev.inmo.micro_utils.coroutines.ExceptionHandler
import dev.inmo.micro_utils.fsm.common.*
import dev.inmo.micro_utils.fsm.common.managers.DefaultStatesManager
import dev.inmo.micro_utils.fsm.common.managers.InMemoryDefaultStatesManagerRepo
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.longPolling
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.startGettingOfUpdatesByLongPolling
import dev.inmo.tgbotapi.types.update.abstracts.Update
import kotlinx.coroutines.CoroutineScope
import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
import dev.inmo.tgbotapi.utils.PreviewFeature
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch
import kotlin.reflect.KClass
class BehaviourContextWithFSMBuilder internal constructor(
@ -83,9 +87,13 @@ inline fun <reified I : State> BehaviourContextWithFSMBuilder.strictlyOn(handler
suspend fun TelegramBot.buildBehaviourWithFSM(
upstreamUpdatesFlow: Flow<Update>? = null,
scope: CoroutineScope = defaultCoroutineScopeProvider(),
statesManager: StatesManager = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
handlersPreset: MutableList<BehaviourWithFSMStateHandlerHolder<*>> = mutableListOf(),
block: suspend BehaviourContextWithFSMBuilder.() -> Unit
) = BehaviourContextWithFSMBuilder(
DefaultBehaviourContext(this, scope, upstreamUpdatesFlow = upstreamUpdatesFlow)
DefaultBehaviourContext(this, scope, upstreamUpdatesFlow = upstreamUpdatesFlow),
statesManager,
handlersPreset
).apply { block() }.build()
/**
@ -98,10 +106,83 @@ suspend fun TelegramBot.buildBehaviourWithFSM(
suspend fun TelegramBot.buildBehaviourWithFSMAndLongPolling(
upstreamUpdatesFlow: Flow<Update>? = null,
scope: CoroutineScope = defaultCoroutineScopeProvider(),
statesManager: StatesManager = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
presetHandlers: MutableList<BehaviourWithFSMStateHandlerHolder<*>> = mutableListOf(),
block: suspend BehaviourContextWithFSMBuilder.() -> Unit
) = buildBehaviourWithFSM(upstreamUpdatesFlow, scope, block).run {
) = buildBehaviourWithFSM(upstreamUpdatesFlow, scope, statesManager, presetHandlers, block).run {
this to scope.launch {
longPolling(this@run, scope = this)
start(this)
start()
longPolling(flowsUpdatesFilter, scope = scope)
}
}
/**
* Use this method in case you wish to make some additional actions with [flowUpdatesFilter].
*
* **WARNING** This method WILL NOT launch any listening of updates. Use something like
* [startGettingOfUpdatesByLongPolling] (or just [longPolling]) or tools for work with webhooks
*
* @see BehaviourContext
* @see BehaviourContextWithFSM
* @see longPolling
* @see strictlyOn
* @see onStateOrSubstate
*/
@PreviewFeature
suspend fun TelegramBot.buildBehaviourWithFSM(
flowUpdatesFilter: FlowsUpdatesFilter,
scope: CoroutineScope = defaultCoroutineScopeProvider(),
defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
statesManager: StatesManager = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
presetHandlers: MutableList<BehaviourWithFSMStateHandlerHolder<*>> = mutableListOf(),
block: CustomBehaviourContextReceiver<BehaviourContextWithFSMBuilder, Unit>
): BehaviourContextWithFSM = BehaviourContextWithFSMBuilder(
BehaviourContext(
this,
scope.let {
if (defaultExceptionsHandler == null) {
it
} else {
it + ContextSafelyExceptionHandler(defaultExceptionsHandler)
}
},
flowUpdatesFilter
),
statesManager,
presetHandlers
).apply { block() }.build()
/**
* Use this method to build bot behaviour with FSM and run it via long polling. In case you wish to use
* [FlowsUpdatesFilter] of result [BehaviourContextWithFSM] for additional manipulations, you must provide external
* [FlowsUpdatesFilter] in other [buildBehaviourWithFSM] function.
*
* @see buildBehaviourWithFSM
* @see BehaviourContext
* @see longPolling
* @see strictlyOn
* @see onStateOrSubstate
*/
@PreviewFeature
suspend fun TelegramBot.buildBehaviourWithFSM(
scope: CoroutineScope = defaultCoroutineScopeProvider(),
defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
statesManager: StatesManager = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
presetHandlers: MutableList<BehaviourWithFSMStateHandlerHolder<*>> = mutableListOf(),
block: BehaviourContextReceiver<Unit>
) = FlowsUpdatesFilter().let {
buildBehaviourWithFSM(
it,
scope,
defaultExceptionsHandler,
statesManager,
presetHandlers,
block
).run {
start()
longPolling(
flowsUpdatesFilter,
scope = scope
)
}
}

View File

@ -0,0 +1,93 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder
import dev.inmo.micro_utils.coroutines.ExceptionHandler
import dev.inmo.micro_utils.fsm.common.StatesManager
import dev.inmo.micro_utils.fsm.common.managers.DefaultStatesManager
import dev.inmo.micro_utils.fsm.common.managers.InMemoryDefaultStatesManagerRepo
import dev.inmo.tgbotapi.bot.Ktor.KtorRequestsExecutorBuilder
import dev.inmo.tgbotapi.bot.Ktor.telegramBot
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.startGettingOfUpdatesByLongPolling
import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlin.coroutines.coroutineContext
/**
* Create bot using [telegramBot] and start listening for updates using [buildBehaviour].
* Use this method in case you wish to make some additional actions with [flowsUpdatesFilter].
*
* **WARNING** This method WILL NOT launch any listening of updates. Use something like
* [startGettingOfUpdatesByLongPolling] or tools for work with webhooks
*
* @return Created bot which has been used to create [BehaviourContext] via [buildBehaviour]
*
* @see [BehaviourContext]
* @see [buildBehaviour]
* @see startGettingOfUpdatesByLongPolling
*/
suspend fun telegramBotWithBehaviourAndFSM(
token: String,
flowsUpdatesFilter: FlowsUpdatesFilter,
scope: CoroutineScope? = null,
apiUrl: String = telegramBotAPIDefaultUrl,
builder: KtorRequestsExecutorBuilder.() -> Unit = {},
defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
statesManager: StatesManager = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
presetHandlers: MutableList<BehaviourWithFSMStateHandlerHolder<*>> = mutableListOf(),
block: BehaviourContextReceiver<Unit>
): TelegramBot = telegramBot(
token,
apiUrl,
builder
).apply {
buildBehaviourWithFSM(
flowsUpdatesFilter,
scope ?: CoroutineScope(coroutineContext),
defaultExceptionsHandler,
statesManager,
presetHandlers,
block
)
}
/**
* Create bot using [telegramBot] and start listening for updates using [buildBehaviour].
* Use this method in case you wish to make some additional actions with [flowsUpdatesFilter].
*
* **WARNING** This method WILL NOT launch any listening of updates. Use something like
* [startGettingOfUpdatesByLongPolling] or tools for work with webhooks
*
* @return Pair of [TelegramBot] and [Job]. This [Job] can be used to stop listening updates in your [block] you passed
* here
*
* @see [BehaviourContext]
* @see [buildBehaviour]
* @see startGettingOfUpdatesByLongPolling
*/
suspend fun telegramBotWithBehaviourAndFSM(
token: String,
scope: CoroutineScope? = null,
apiUrl: String = telegramBotAPIDefaultUrl,
builder: KtorRequestsExecutorBuilder.() -> Unit = {},
defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
statesManager: StatesManager = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
presetHandlers: MutableList<BehaviourWithFSMStateHandlerHolder<*>> = mutableListOf(),
block: BehaviourContextReceiver<Unit>
): Pair<TelegramBot, Job> {
return telegramBot(
token,
apiUrl,
builder
).let {
it to it.buildBehaviourWithFSM (
scope ?: CoroutineScope(coroutineContext),
defaultExceptionsHandler,
statesManager,
presetHandlers,
block
)
}
}