mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2024-11-24 19:18:44 +00:00
Merge branch 'master' into 1.0.0
This commit is contained in:
commit
a2206b99a2
16
CHANGELOG.md
16
CHANGELOG.md
@ -47,6 +47,22 @@ __All the `tgbotapi.extensions.*` packages have been removed__
|
|||||||
* `BehaviourBuilder`:
|
* `BehaviourBuilder`:
|
||||||
* `SimpleFilter` now is a `fun interface` instead of just callback (fix of [#546](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/546))
|
* `SimpleFilter` now is a `fun interface` instead of just callback (fix of [#546](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/546))
|
||||||
|
|
||||||
|
## 0.38.20
|
||||||
|
|
||||||
|
* `BehaviourBuilder FSM`:
|
||||||
|
* Hotfixes
|
||||||
|
* `WebApps`:
|
||||||
|
* New extension `TelegramBot#answerWebAppQuery`
|
||||||
|
* New function `handleResult`
|
||||||
|
|
||||||
|
## 0.38.19
|
||||||
|
|
||||||
|
* `BehaviourBuilder`:
|
||||||
|
* Hotfixes
|
||||||
|
* `BehaviourBuilder FSM`:
|
||||||
|
* `BehaviourContextWithFSMBuilder` deprecated in favor to `BehaviourContextWithFSM`
|
||||||
|
* Now it is possible to define additional handlers in subcontexts of `BehaviourBuilderWithFSM`
|
||||||
|
|
||||||
## 0.38.18
|
## 0.38.18
|
||||||
|
|
||||||
* `Core`:
|
* `Core`:
|
||||||
|
@ -9,6 +9,8 @@ import dev.inmo.micro_utils.coroutines.accumulatorFlow
|
|||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.channels.BufferOverflow
|
import kotlinx.coroutines.channels.BufferOverflow
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
|
import kotlin.jvm.JvmName
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface which combine [BehaviourContext] and [StatesMachine]. Subcontext of triggers and states contexts must have
|
* Interface which combine [BehaviourContext] and [StatesMachine]. Subcontext of triggers and states contexts must have
|
||||||
@ -26,9 +28,30 @@ interface BehaviourContextWithFSM<T : State> : BehaviourContext, StatesMachine<T
|
|||||||
handlers: List<BehaviourWithFSMStateHandlerHolder<*, T>>
|
handlers: List<BehaviourWithFSMStateHandlerHolder<*, T>>
|
||||||
): T? {
|
): T? {
|
||||||
return handlers.firstOrNull { it.checkHandleable(state) } ?.run {
|
return handlers.firstOrNull { it.checkHandleable(state) } ?.run {
|
||||||
handleState(contextUpdatesFlow, state)
|
doInSubContext(updatesUpstreamFlow = contextUpdatesFlow) {
|
||||||
|
handleState(state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add NON STRICT [handler] to list of available in future [BehaviourContextWithFSM]. Non strict means that
|
||||||
|
* for input [State] will be used [KClass.isInstance] and any inheritor of [kClass] will pass this requirement
|
||||||
|
*
|
||||||
|
* @see BehaviourWithFSMStateHandlerHolder
|
||||||
|
* @see onStateOrSubstate
|
||||||
|
*/
|
||||||
|
fun <I : T> add(kClass: KClass<I>, strict: Boolean = false, handler: BehaviourWithFSMStateHandler<I, T>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add STRICT [handler] to list of available in future [BehaviourContextWithFSM]. Strict means that
|
||||||
|
* for input [State] will be used [State]::class == [kClass] and any [State] with exactly the same type will pass
|
||||||
|
* requirements
|
||||||
|
*
|
||||||
|
* @see BehaviourWithFSMStateHandlerHolder
|
||||||
|
* @see strictlyOn
|
||||||
|
*/
|
||||||
|
fun <I : T> addStrict(kClass: KClass<I>, handler: BehaviourWithFSMStateHandler<I, T>) = add(kClass, strict = true, handler)
|
||||||
|
|
||||||
override fun copy(
|
override fun copy(
|
||||||
bot: TelegramBot,
|
bot: TelegramBot,
|
||||||
@ -48,6 +71,28 @@ interface BehaviourContextWithFSM<T : State> : BehaviourContext, StatesMachine<T
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add NON STRICT [handler] to list of available in future [BehaviourContextWithFSM]. Non strict means that
|
||||||
|
* for input [State] will be used [KClass.isInstance] and any inheritor of [kClass] will pass this requirement
|
||||||
|
*
|
||||||
|
* @see BehaviourWithFSMStateHandlerHolder
|
||||||
|
* @see BehaviourContextWithFSM.add
|
||||||
|
*/
|
||||||
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
inline fun <reified I : O, O: State> BehaviourContextWithFSM<O>.onStateOrSubstate(handler: BehaviourWithFSMStateHandler<I, O>) = add(I::class, strict = false, handler)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add STRICT [handler] to list of available in future [BehaviourContextWithFSM]. Strict means that
|
||||||
|
* for input [State] will be used [State]::class == [kClass] and any [State] with exactly the same type will pass
|
||||||
|
* requirements
|
||||||
|
*
|
||||||
|
* @see BehaviourWithFSMStateHandlerHolder
|
||||||
|
* @see BehaviourContextWithFSM.addStrict
|
||||||
|
*/
|
||||||
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
inline fun <reified I : O, O: State> BehaviourContextWithFSM<O>.strictlyOn(handler: BehaviourWithFSMStateHandler<I, O>) = addStrict(I::class, handler)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default realization of [BehaviourContextWithFSM]. It uses [behaviourContext] as a base for this object as
|
* Default realization of [BehaviourContextWithFSM]. It uses [behaviourContext] as a base for this object as
|
||||||
* [BehaviourContext], but managing substates contexts updates for avoiding of updates lost between states
|
* [BehaviourContext], but managing substates contexts updates for avoiding of updates lost between states
|
||||||
@ -58,6 +103,9 @@ class DefaultBehaviourContextWithFSM<T : State>(
|
|||||||
private val handlers: List<BehaviourWithFSMStateHandlerHolder<*, T>>
|
private val handlers: List<BehaviourWithFSMStateHandlerHolder<*, T>>
|
||||||
) : BehaviourContext by behaviourContext, BehaviourContextWithFSM<T> {
|
) : BehaviourContext by behaviourContext, BehaviourContextWithFSM<T> {
|
||||||
private val updatesFlows = mutableMapOf<Any, Flow<Update>>()
|
private val updatesFlows = mutableMapOf<Any, Flow<Update>>()
|
||||||
|
private val additionalHandlers = mutableListOf<BehaviourWithFSMStateHandlerHolder<*, T>>()
|
||||||
|
private var actualHandlersList = additionalHandlers + handlers
|
||||||
|
|
||||||
private fun getContextUpdatesFlow(context: Any) = updatesFlows.getOrPut(context) {
|
private fun getContextUpdatesFlow(context: Any) = updatesFlows.getOrPut(context) {
|
||||||
allUpdatesFlow.accumulatorFlow(scope)
|
allUpdatesFlow.accumulatorFlow(scope)
|
||||||
}
|
}
|
||||||
@ -65,12 +113,17 @@ class DefaultBehaviourContextWithFSM<T : State>(
|
|||||||
override suspend fun StatesMachine<in T>.handleState(state: T): T? = launchStateHandling(
|
override suspend fun StatesMachine<in T>.handleState(state: T): T? = launchStateHandling(
|
||||||
state,
|
state,
|
||||||
allUpdatesFlow,
|
allUpdatesFlow,
|
||||||
handlers
|
actualHandlersList
|
||||||
)
|
)
|
||||||
|
|
||||||
|
override fun <I : T> add(kClass: KClass<I>, strict: Boolean, handler: BehaviourWithFSMStateHandler<I, T>) {
|
||||||
|
additionalHandlers.add(BehaviourWithFSMStateHandlerHolder(kClass, strict, handler))
|
||||||
|
actualHandlersList = additionalHandlers + handlers
|
||||||
|
}
|
||||||
|
|
||||||
override fun start(scope: CoroutineScope): Job = scope.launchSafelyWithoutExceptions {
|
override fun start(scope: CoroutineScope): Job = scope.launchSafelyWithoutExceptions {
|
||||||
val statePerformer: suspend (T) -> Unit = { state: T ->
|
val statePerformer: suspend (T) -> Unit = { state: T ->
|
||||||
val newState = launchStateHandling(state, getContextUpdatesFlow(state.context), handlers)
|
val newState = launchStateHandling(state, getContextUpdatesFlow(state.context), actualHandlersList)
|
||||||
if (newState != null) {
|
if (newState != null) {
|
||||||
statesManager.update(state, newState)
|
statesManager.update(state, newState)
|
||||||
} else {
|
} else {
|
||||||
@ -94,6 +147,26 @@ class DefaultBehaviourContextWithFSM<T : State>(
|
|||||||
launch { statePerformer(it) }
|
launch { statePerformer(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Add NON STRICT [handler] to list of available in future [BehaviourContextWithFSM]. Non strict means that
|
||||||
|
* for input [State] will be used [KClass.isInstance] and any inheritor of [kClass] will pass this requirement
|
||||||
|
*
|
||||||
|
* @see BehaviourWithFSMStateHandlerHolder
|
||||||
|
* @see BehaviourContextWithFSM.add
|
||||||
|
*/
|
||||||
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
inline fun <reified I : T> onStateOrSubstate(handler: BehaviourWithFSMStateHandler<I, T>) = add(I::class, strict = false, handler)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add STRICT [handler] to list of available in future [BehaviourContextWithFSM]. Strict means that
|
||||||
|
* for input [State] will be used [State]::class == [kClass] and any [State] with exactly the same type will pass
|
||||||
|
* requirements
|
||||||
|
*
|
||||||
|
* @see BehaviourWithFSMStateHandlerHolder
|
||||||
|
* @see BehaviourContextWithFSM.addStrict
|
||||||
|
*/
|
||||||
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
inline fun <reified I : T> strictlyOn(handler: BehaviourWithFSMStateHandler<I, T>) = addStrict(I::class, handler)
|
||||||
|
|
||||||
override suspend fun startChain(state: T) {
|
override suspend fun startChain(state: T) {
|
||||||
statesManager.startChain(state)
|
statesManager.startChain(state)
|
||||||
@ -106,7 +179,7 @@ class DefaultBehaviourContextWithFSM<T : State>(
|
|||||||
onBufferOverflow: BufferOverflow,
|
onBufferOverflow: BufferOverflow,
|
||||||
upstreamUpdatesFlow: Flow<Update>?,
|
upstreamUpdatesFlow: Flow<Update>?,
|
||||||
updatesFilter: BehaviourContextAndTypeReceiver<Boolean, Update>?
|
updatesFilter: BehaviourContextAndTypeReceiver<Boolean, Update>?
|
||||||
): BehaviourContextWithFSM<T> = BehaviourContextWithFSM(
|
): DefaultBehaviourContextWithFSM<T> = BehaviourContextWithFSM(
|
||||||
behaviourContext.copy(bot, scope, broadcastChannelsSize, onBufferOverflow, upstreamUpdatesFlow, updatesFilter),
|
behaviourContext.copy(bot, scope, broadcastChannelsSize, onBufferOverflow, upstreamUpdatesFlow, updatesFilter),
|
||||||
handlers,
|
handlers,
|
||||||
statesManager
|
statesManager
|
||||||
|
@ -14,70 +14,8 @@ import kotlinx.coroutines.*
|
|||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
class BehaviourContextWithFSMBuilder<T : State> internal constructor(
|
@Deprecated("Will be removed soon")
|
||||||
private val resultBehaviourContext: BehaviourContextWithFSM<T>,
|
typealias BehaviourContextWithFSMBuilder<T> = BehaviourContextWithFSM<T>
|
||||||
private val handlers: MutableList<BehaviourWithFSMStateHandlerHolder<*, T>>
|
|
||||||
) : BehaviourContextWithFSM<T> by resultBehaviourContext {
|
|
||||||
internal constructor(
|
|
||||||
baseBehaviourContext: BehaviourContext,
|
|
||||||
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
|
|
||||||
handlers: MutableList<BehaviourWithFSMStateHandlerHolder<*, T>> = mutableListOf()
|
|
||||||
) : this(DefaultBehaviourContextWithFSM(baseBehaviourContext, statesManager, handlers), handlers)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add NON STRICT [handler] to list of available in future [BehaviourContextWithFSM]. Non strict means that
|
|
||||||
* for input [State] will be used [KClass.isInstance] and any inheritor of [kClass] will pass this requirement
|
|
||||||
*
|
|
||||||
* @see BehaviourWithFSMStateHandlerHolder
|
|
||||||
* @see onStateOrSubstate
|
|
||||||
*/
|
|
||||||
fun <I : T> add(kClass: KClass<I>, handler: BehaviourWithFSMStateHandler<I, T>) {
|
|
||||||
handlers.add(BehaviourWithFSMStateHandlerHolder(kClass, false, handler))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add STRICT [handler] to list of available in future [BehaviourContextWithFSM]. Strict means that
|
|
||||||
* for input [State] will be used [State]::class == [kClass] and any [State] with exactly the same type will pass
|
|
||||||
* requirements
|
|
||||||
*
|
|
||||||
* @see BehaviourWithFSMStateHandlerHolder
|
|
||||||
* @see strictlyOn
|
|
||||||
*/
|
|
||||||
fun <I : T> addStrict(kClass: KClass<I>, handler: BehaviourWithFSMStateHandler<I, T>) {
|
|
||||||
handlers.add(BehaviourWithFSMStateHandlerHolder(kClass, true, handler))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add NON STRICT [handler] to list of available in future [BehaviourContextWithFSM]. Non strict means that
|
|
||||||
* for input [State] will be used [KClass.isInstance] and any inheritor of [kClass] will pass this requirement
|
|
||||||
*
|
|
||||||
* @see BehaviourWithFSMStateHandlerHolder
|
|
||||||
* @see BehaviourContextWithFSMBuilder.add
|
|
||||||
*/
|
|
||||||
@Suppress("MemberVisibilityCanBePrivate")
|
|
||||||
inline fun <reified I : T> onStateOrSubstate(handler: BehaviourWithFSMStateHandler<I, T>) {
|
|
||||||
add(I::class, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add STRICT [handler] to list of available in future [BehaviourContextWithFSM]. Strict means that
|
|
||||||
* for input [State] will be used [State]::class == [kClass] and any [State] with exactly the same type will pass
|
|
||||||
* requirements
|
|
||||||
*
|
|
||||||
* @see BehaviourWithFSMStateHandlerHolder
|
|
||||||
* @see BehaviourContextWithFSMBuilder.addStrict
|
|
||||||
*/
|
|
||||||
@Suppress("MemberVisibilityCanBePrivate")
|
|
||||||
inline fun <reified I : T> strictlyOn(handler: BehaviourWithFSMStateHandler<I, T>) {
|
|
||||||
addStrict(I::class, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns completed [resultBehaviourContext], [handlers] and [statesManager]
|
|
||||||
*/
|
|
||||||
internal fun build() = resultBehaviourContext
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates [BehaviourContextWithFSM] via creating of [DefaultBehaviourContext] with [this] as [TelegramBot],
|
* Creates [BehaviourContextWithFSM] via creating of [DefaultBehaviourContext] with [this] as [TelegramBot],
|
||||||
@ -94,17 +32,17 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSM(
|
|||||||
scope: CoroutineScope = defaultCoroutineScopeProvider(),
|
scope: CoroutineScope = defaultCoroutineScopeProvider(),
|
||||||
defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
|
defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
|
||||||
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
|
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
|
||||||
presetHandlers: MutableList<BehaviourWithFSMStateHandlerHolder<*, T>> = mutableListOf(),
|
presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(),
|
||||||
block: CustomBehaviourContextReceiver<BehaviourContextWithFSMBuilder<T>, Unit>
|
block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit>
|
||||||
): BehaviourContextWithFSM<T> = BehaviourContextWithFSMBuilder(
|
): DefaultBehaviourContextWithFSM<T> = BehaviourContextWithFSM(
|
||||||
DefaultBehaviourContext(
|
DefaultBehaviourContext(
|
||||||
this,
|
this,
|
||||||
defaultExceptionsHandler ?.let { scope + ContextSafelyExceptionHandler(it) } ?: scope,
|
defaultExceptionsHandler ?.let { scope + ContextSafelyExceptionHandler(it) } ?: scope,
|
||||||
upstreamUpdatesFlow = upstreamUpdatesFlow
|
upstreamUpdatesFlow = upstreamUpdatesFlow
|
||||||
),
|
),
|
||||||
statesManager,
|
presetHandlers,
|
||||||
presetHandlers
|
statesManager
|
||||||
).apply { block() }.build()
|
).apply { block() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use [buildBehaviourWithFSM] to create [BehaviourContextWithFSM] and launch getting of updates
|
* Use [buildBehaviourWithFSM] to create [BehaviourContextWithFSM] and launch getting of updates
|
||||||
@ -116,9 +54,9 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
|
|||||||
scope: CoroutineScope = defaultCoroutineScopeProvider(),
|
scope: CoroutineScope = defaultCoroutineScopeProvider(),
|
||||||
defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
|
defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
|
||||||
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
|
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
|
||||||
presetHandlers: MutableList<BehaviourWithFSMStateHandlerHolder<*, T>> = mutableListOf(),
|
presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(),
|
||||||
block: CustomBehaviourContextReceiver<BehaviourContextWithFSMBuilder<T>, Unit>
|
block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit>
|
||||||
): Pair<BehaviourContextWithFSM<T>, Job> = buildBehaviourWithFSM(
|
): Pair<DefaultBehaviourContextWithFSM<T>, Job> = buildBehaviourWithFSM(
|
||||||
upstreamUpdatesFlow,
|
upstreamUpdatesFlow,
|
||||||
scope,
|
scope,
|
||||||
defaultExceptionsHandler,
|
defaultExceptionsHandler,
|
||||||
@ -147,8 +85,8 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
|
|||||||
* @see BehaviourContext
|
* @see BehaviourContext
|
||||||
* @see BehaviourContextWithFSM
|
* @see BehaviourContextWithFSM
|
||||||
* @see longPolling
|
* @see longPolling
|
||||||
* @see BehaviourContextWithFSMBuilder.strictlyOn
|
* @see BehaviourContextWithFSM.strictlyOn
|
||||||
* @see BehaviourContextWithFSMBuilder.onStateOrSubstate
|
* @see BehaviourContextWithFSM.onStateOrSubstate
|
||||||
*/
|
*/
|
||||||
@PreviewFeature
|
@PreviewFeature
|
||||||
suspend fun <T : State> TelegramBot.buildBehaviourWithFSM(
|
suspend fun <T : State> TelegramBot.buildBehaviourWithFSM(
|
||||||
@ -156,17 +94,17 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSM(
|
|||||||
scope: CoroutineScope = defaultCoroutineScopeProvider(),
|
scope: CoroutineScope = defaultCoroutineScopeProvider(),
|
||||||
defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
|
defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
|
||||||
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
|
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
|
||||||
presetHandlers: MutableList<BehaviourWithFSMStateHandlerHolder<*, T>> = mutableListOf(),
|
presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(),
|
||||||
block: CustomBehaviourContextReceiver<BehaviourContextWithFSMBuilder<T>, Unit>
|
block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit>
|
||||||
): BehaviourContextWithFSM<T> = BehaviourContextWithFSMBuilder(
|
): DefaultBehaviourContextWithFSM<T> = BehaviourContextWithFSM(
|
||||||
DefaultBehaviourContext(
|
DefaultBehaviourContext(
|
||||||
this,
|
this,
|
||||||
defaultExceptionsHandler ?.let { scope + ContextSafelyExceptionHandler(it) } ?: scope,
|
defaultExceptionsHandler ?.let { scope + ContextSafelyExceptionHandler(it) } ?: scope,
|
||||||
upstreamUpdatesFlow = flowUpdatesFilter.allUpdatesFlow
|
upstreamUpdatesFlow = flowUpdatesFilter.allUpdatesFlow
|
||||||
),
|
),
|
||||||
statesManager,
|
presetHandlers,
|
||||||
presetHandlers
|
statesManager
|
||||||
).apply { block() }.build()
|
).apply { block() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use [buildBehaviourWithFSM] to create [BehaviourContextWithFSM] and launch getting of updates
|
* Use [buildBehaviourWithFSM] to create [BehaviourContextWithFSM] and launch getting of updates
|
||||||
@ -176,16 +114,16 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSM(
|
|||||||
* @see buildBehaviourWithFSMAndStartLongPolling
|
* @see buildBehaviourWithFSMAndStartLongPolling
|
||||||
* @see BehaviourContext
|
* @see BehaviourContext
|
||||||
* @see longPolling
|
* @see longPolling
|
||||||
* @see BehaviourContextWithFSMBuilder.strictlyOn
|
* @see BehaviourContextWithFSM.strictlyOn
|
||||||
* @see BehaviourContextWithFSMBuilder.onStateOrSubstate
|
* @see BehaviourContextWithFSM.onStateOrSubstate
|
||||||
*/
|
*/
|
||||||
@PreviewFeature
|
@PreviewFeature
|
||||||
suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
|
suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
|
||||||
scope: CoroutineScope = defaultCoroutineScopeProvider(),
|
scope: CoroutineScope = defaultCoroutineScopeProvider(),
|
||||||
defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
|
defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
|
||||||
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
|
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
|
||||||
presetHandlers: MutableList<BehaviourWithFSMStateHandlerHolder<*, T>> = mutableListOf(),
|
presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(),
|
||||||
block: CustomBehaviourContextReceiver<BehaviourContextWithFSMBuilder<T>, Unit>
|
block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit>
|
||||||
) = FlowsUpdatesFilter().let {
|
) = FlowsUpdatesFilter().let {
|
||||||
buildBehaviourWithFSM(
|
buildBehaviourWithFSM(
|
||||||
it,
|
it,
|
||||||
|
@ -34,21 +34,12 @@ class BehaviourWithFSMStateHandlerHolder<I : O, O : State>(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handling of state :)
|
* Handling of state :)
|
||||||
*
|
|
||||||
* @param contextUpdatesFlow This [Flow] will be used as source of updates. By contract, this [Flow] must be common
|
|
||||||
* for all [State]s of incoming [state] [State.context] and for the whole chain inside of [BehaviourContextWithFSM]
|
|
||||||
*/
|
*/
|
||||||
suspend fun BehaviourContextWithFSM<in O>.handleState(
|
suspend fun BehaviourContextWithFSM<in O>.handleState(
|
||||||
contextUpdatesFlow: Flow<Update>,
|
|
||||||
state: O
|
state: O
|
||||||
): O? {
|
): O? = with(delegateTo) {
|
||||||
val subscope = scope.LinkedSupervisorScope()
|
|
||||||
return with(copy(scope = subscope, upstreamUpdatesFlow = contextUpdatesFlow)) {
|
|
||||||
with(delegateTo) {
|
|
||||||
handleState(state as I)
|
handleState(state as I)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified I : O, O : State> BehaviourWithFSMStateHandlerHolder(
|
inline fun <reified I : O, O : State> BehaviourWithFSMStateHandlerHolder(
|
||||||
|
@ -37,9 +37,9 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSM(
|
|||||||
builder: KtorRequestsExecutorBuilder.() -> Unit = {},
|
builder: KtorRequestsExecutorBuilder.() -> Unit = {},
|
||||||
defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
|
defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
|
||||||
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
|
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
|
||||||
presetHandlers: MutableList<BehaviourWithFSMStateHandlerHolder<*, T>> = mutableListOf(),
|
presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(),
|
||||||
testServer: Boolean = false,
|
testServer: Boolean = false,
|
||||||
block: CustomBehaviourContextReceiver<BehaviourContextWithFSMBuilder<T>, Unit>
|
block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit>
|
||||||
): TelegramBot = telegramBot(
|
): TelegramBot = telegramBot(
|
||||||
token,
|
token,
|
||||||
apiUrl,
|
apiUrl,
|
||||||
@ -74,9 +74,9 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSMAndStartLongPolling(
|
|||||||
builder: KtorRequestsExecutorBuilder.() -> Unit = {},
|
builder: KtorRequestsExecutorBuilder.() -> Unit = {},
|
||||||
defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
|
defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
|
||||||
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
|
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
|
||||||
presetHandlers: MutableList<BehaviourWithFSMStateHandlerHolder<*, T>> = mutableListOf(),
|
presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(),
|
||||||
testServer: Boolean = false,
|
testServer: Boolean = false,
|
||||||
block: CustomBehaviourContextReceiver<BehaviourContextWithFSMBuilder<T>, Unit>
|
block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit>
|
||||||
): Pair<TelegramBot, Job> {
|
): Pair<TelegramBot, Job> {
|
||||||
return telegramBot(
|
return telegramBot(
|
||||||
token,
|
token,
|
||||||
|
@ -6,6 +6,9 @@ import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.InlineQ
|
|||||||
import dev.inmo.tgbotapi.types.webapps.query.SentWebAppMessage
|
import dev.inmo.tgbotapi.types.webapps.query.SentWebAppMessage
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param webAppQueryId [dev.inmo.tgbotapi.webapps.WebAppInitData.queryId]
|
||||||
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
data class AnswerWebAppQuery(
|
data class AnswerWebAppQuery(
|
||||||
@SerialName(webAppQueryIdField)
|
@SerialName(webAppQueryIdField)
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
package dev.inmo.tgbotapi.webapps
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||||
|
import dev.inmo.tgbotapi.requests.answers.AnswerWebAppQuery
|
||||||
|
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.InlineQueryResult
|
||||||
|
|
||||||
|
suspend fun TelegramBot.answerWebAppQuery(
|
||||||
|
result: InlineQueryResult
|
||||||
|
) = webApp.initDataUnsafe.queryId ?.let {
|
||||||
|
execute(AnswerWebAppQuery(it, result))
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package dev.inmo.tgbotapi.webapps
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.types.WebAppQueryId
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param onSendData Should return the data which must be used in [WebApp.sendData]. If returns null, data will not be sent
|
||||||
|
* @param onAnswerWebAppQuery In case if [WebAppInitData.queryId] is presented in [WebApp.initDataUnsafe], will be called
|
||||||
|
* that callback. Before and after calling of this callback will not be used any method of answering to the telegram
|
||||||
|
* system, so, you must use something like [answerWebAppQuery] by yourself to send the result
|
||||||
|
*/
|
||||||
|
inline fun handleResult(
|
||||||
|
onSendData: () -> String?,
|
||||||
|
onAnswerWebAppQuery: (WebAppQueryId) -> Unit
|
||||||
|
) {
|
||||||
|
webApp.initDataUnsafe.queryId ?.let {
|
||||||
|
onAnswerWebAppQuery(it)
|
||||||
|
} ?: webApp.sendData(onSendData() ?: return)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user