1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2024-11-29 13:38:43 +00:00

Compare commits

..

No commits in common. "efd1c8f83a9bcdfc8be205242412ac92a08d882a" and "ab5937449c716a96241150cf9dbaaf580ed4757e" have entirely different histories.

14 changed files with 129 additions and 193 deletions

View File

@ -7,8 +7,6 @@
* `MicroUtils`: `0.9.20` -> `0.9.24` * `MicroUtils`: `0.9.20` -> `0.9.24`
* `Core`: * `Core`:
* Fixes in `MessageContent#serializationModule` * Fixes in `MessageContent#serializationModule`
* `BehaviourBuilder`:
* Add triggers for `DataCallbackQuery` and subtypes with regex checking of data
## 0.38.14 ## 0.38.14

View File

@ -12,7 +12,7 @@ klock_version=2.7.0
uuid_version=0.4.0 uuid_version=0.4.0
ktor_version=1.6.8 ktor_version=1.6.8
micro_utils_version=0.9.24 micro_utils_version=0.9.25
javax_activation_version=1.1.1 javax_activation_version=1.1.1

View File

@ -6,6 +6,7 @@ import dev.inmo.micro_utils.fsm.common.*
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.types.update.abstracts.Update import dev.inmo.tgbotapi.types.update.abstracts.Update
import dev.inmo.micro_utils.coroutines.accumulatorFlow import dev.inmo.micro_utils.coroutines.accumulatorFlow
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers.TelegramHandlersRegistrar
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
@ -36,6 +37,7 @@ interface BehaviourContextWithFSM<T : State> : BehaviourContext, StatesMachine<T
broadcastChannelsSize: Int, broadcastChannelsSize: Int,
onBufferOverflow: BufferOverflow, onBufferOverflow: BufferOverflow,
upstreamUpdatesFlow: Flow<Update>?, upstreamUpdatesFlow: Flow<Update>?,
telegramHandlersRegistrar: TelegramHandlersRegistrar,
updatesFilter: BehaviourContextAndTypeReceiver<Boolean, Update>? updatesFilter: BehaviourContextAndTypeReceiver<Boolean, Update>?
): BehaviourContextWithFSM<T> ): BehaviourContextWithFSM<T>
@ -105,9 +107,10 @@ class DefaultBehaviourContextWithFSM<T : State>(
broadcastChannelsSize: Int, broadcastChannelsSize: Int,
onBufferOverflow: BufferOverflow, onBufferOverflow: BufferOverflow,
upstreamUpdatesFlow: Flow<Update>?, upstreamUpdatesFlow: Flow<Update>?,
telegramHandlersRegistrar: TelegramHandlersRegistrar,
updatesFilter: BehaviourContextAndTypeReceiver<Boolean, Update>? updatesFilter: BehaviourContextAndTypeReceiver<Boolean, Update>?
): BehaviourContextWithFSM<T> = BehaviourContextWithFSM( ): BehaviourContextWithFSM<T> = BehaviourContextWithFSM(
behaviourContext.copy(bot, scope, broadcastChannelsSize, onBufferOverflow, upstreamUpdatesFlow, updatesFilter), behaviourContext.copy(bot, scope, broadcastChannelsSize, onBufferOverflow, upstreamUpdatesFlow, telegramHandlersRegistrar, updatesFilter),
handlers, handlers,
statesManager statesManager
) )

View File

@ -5,6 +5,8 @@ import dev.inmo.micro_utils.fsm.common.*
import dev.inmo.micro_utils.fsm.common.managers.DefaultStatesManager import dev.inmo.micro_utils.fsm.common.managers.DefaultStatesManager
import dev.inmo.micro_utils.fsm.common.managers.InMemoryDefaultStatesManagerRepo import dev.inmo.micro_utils.fsm.common.managers.InMemoryDefaultStatesManagerRepo
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers.DefaultTelegramHandlersRegistrar
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers.TelegramHandlersRegistrar
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.longPolling 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.startGettingOfUpdatesByLongPolling
import dev.inmo.tgbotapi.types.update.abstracts.Update import dev.inmo.tgbotapi.types.update.abstracts.Update
@ -95,12 +97,14 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSM(
defaultExceptionsHandler: ExceptionHandler<Unit>? = null, defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()), statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
presetHandlers: MutableList<BehaviourWithFSMStateHandlerHolder<*, T>> = mutableListOf(), presetHandlers: MutableList<BehaviourWithFSMStateHandlerHolder<*, T>> = mutableListOf(),
telegramHandlersRegistrar: TelegramHandlersRegistrar = DefaultTelegramHandlersRegistrar(),
block: CustomBehaviourContextReceiver<BehaviourContextWithFSMBuilder<T>, Unit> block: CustomBehaviourContextReceiver<BehaviourContextWithFSMBuilder<T>, Unit>
): BehaviourContextWithFSM<T> = BehaviourContextWithFSMBuilder( ): BehaviourContextWithFSM<T> = BehaviourContextWithFSMBuilder(
DefaultBehaviourContext( DefaultBehaviourContext(
this, this,
defaultExceptionsHandler ?.let { scope + ContextSafelyExceptionHandler(it) } ?: scope, defaultExceptionsHandler ?.let { scope + ContextSafelyExceptionHandler(it) } ?: scope,
upstreamUpdatesFlow = upstreamUpdatesFlow upstreamUpdatesFlow = upstreamUpdatesFlow,
telegramHandlersRegistrar = telegramHandlersRegistrar
), ),
statesManager, statesManager,
presetHandlers presetHandlers
@ -117,6 +121,7 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
defaultExceptionsHandler: ExceptionHandler<Unit>? = null, defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()), statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
presetHandlers: MutableList<BehaviourWithFSMStateHandlerHolder<*, T>> = mutableListOf(), presetHandlers: MutableList<BehaviourWithFSMStateHandlerHolder<*, T>> = mutableListOf(),
telegramHandlersRegistrar: TelegramHandlersRegistrar = DefaultTelegramHandlersRegistrar(),
block: CustomBehaviourContextReceiver<BehaviourContextWithFSMBuilder<T>, Unit> block: CustomBehaviourContextReceiver<BehaviourContextWithFSMBuilder<T>, Unit>
): Pair<BehaviourContextWithFSM<T>, Job> = buildBehaviourWithFSM( ): Pair<BehaviourContextWithFSM<T>, Job> = buildBehaviourWithFSM(
upstreamUpdatesFlow, upstreamUpdatesFlow,
@ -124,6 +129,7 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
defaultExceptionsHandler, defaultExceptionsHandler,
statesManager, statesManager,
presetHandlers, presetHandlers,
telegramHandlersRegistrar,
block block
).run { ).run {
this to scope.launch { this to scope.launch {
@ -157,12 +163,14 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSM(
defaultExceptionsHandler: ExceptionHandler<Unit>? = null, defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()), statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
presetHandlers: MutableList<BehaviourWithFSMStateHandlerHolder<*, T>> = mutableListOf(), presetHandlers: MutableList<BehaviourWithFSMStateHandlerHolder<*, T>> = mutableListOf(),
telegramHandlersRegistrar: TelegramHandlersRegistrar = DefaultTelegramHandlersRegistrar(),
block: CustomBehaviourContextReceiver<BehaviourContextWithFSMBuilder<T>, Unit> block: CustomBehaviourContextReceiver<BehaviourContextWithFSMBuilder<T>, Unit>
): BehaviourContextWithFSM<T> = BehaviourContextWithFSMBuilder( ): BehaviourContextWithFSM<T> = BehaviourContextWithFSMBuilder(
DefaultBehaviourContext( DefaultBehaviourContext(
this, this,
defaultExceptionsHandler ?.let { scope + ContextSafelyExceptionHandler(it) } ?: scope, defaultExceptionsHandler ?.let { scope + ContextSafelyExceptionHandler(it) } ?: scope,
upstreamUpdatesFlow = flowUpdatesFilter.allUpdatesFlow upstreamUpdatesFlow = flowUpdatesFilter.allUpdatesFlow,
telegramHandlersRegistrar = telegramHandlersRegistrar
), ),
statesManager, statesManager,
presetHandlers presetHandlers
@ -185,6 +193,7 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
defaultExceptionsHandler: ExceptionHandler<Unit>? = null, defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()), statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
presetHandlers: MutableList<BehaviourWithFSMStateHandlerHolder<*, T>> = mutableListOf(), presetHandlers: MutableList<BehaviourWithFSMStateHandlerHolder<*, T>> = mutableListOf(),
telegramHandlersRegistrar: TelegramHandlersRegistrar = DefaultTelegramHandlersRegistrar(),
block: CustomBehaviourContextReceiver<BehaviourContextWithFSMBuilder<T>, Unit> block: CustomBehaviourContextReceiver<BehaviourContextWithFSMBuilder<T>, Unit>
) = FlowsUpdatesFilter().let { ) = FlowsUpdatesFilter().let {
buildBehaviourWithFSM( buildBehaviourWithFSM(
@ -193,6 +202,7 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
defaultExceptionsHandler, defaultExceptionsHandler,
statesManager, statesManager,
presetHandlers, presetHandlers,
telegramHandlersRegistrar,
block block
).run { ).run {
start() start()

View File

@ -8,6 +8,8 @@ import dev.inmo.micro_utils.fsm.common.managers.InMemoryDefaultStatesManagerRepo
import dev.inmo.tgbotapi.bot.Ktor.KtorRequestsExecutorBuilder import dev.inmo.tgbotapi.bot.Ktor.KtorRequestsExecutorBuilder
import dev.inmo.tgbotapi.bot.Ktor.telegramBot import dev.inmo.tgbotapi.bot.Ktor.telegramBot
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers.DefaultTelegramHandlersRegistrar
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers.TelegramHandlersRegistrar
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.startGettingOfUpdatesByLongPolling import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.startGettingOfUpdatesByLongPolling
import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl
@ -38,6 +40,7 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSM(
defaultExceptionsHandler: ExceptionHandler<Unit>? = null, defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()), statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
presetHandlers: MutableList<BehaviourWithFSMStateHandlerHolder<*, T>> = mutableListOf(), presetHandlers: MutableList<BehaviourWithFSMStateHandlerHolder<*, T>> = mutableListOf(),
telegramHandlersRegistrar: TelegramHandlersRegistrar = DefaultTelegramHandlersRegistrar(),
block: CustomBehaviourContextReceiver<BehaviourContextWithFSMBuilder<T>, Unit> block: CustomBehaviourContextReceiver<BehaviourContextWithFSMBuilder<T>, Unit>
): TelegramBot = telegramBot( ): TelegramBot = telegramBot(
token, token,
@ -50,6 +53,7 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSM(
defaultExceptionsHandler, defaultExceptionsHandler,
statesManager, statesManager,
presetHandlers, presetHandlers,
telegramHandlersRegistrar,
block block
) )
} }
@ -73,6 +77,7 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSMAndStartLongPolling(
defaultExceptionsHandler: ExceptionHandler<Unit>? = null, defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()), statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
presetHandlers: MutableList<BehaviourWithFSMStateHandlerHolder<*, T>> = mutableListOf(), presetHandlers: MutableList<BehaviourWithFSMStateHandlerHolder<*, T>> = mutableListOf(),
telegramHandlersRegistrar: TelegramHandlersRegistrar = DefaultTelegramHandlersRegistrar(),
block: CustomBehaviourContextReceiver<BehaviourContextWithFSMBuilder<T>, Unit> block: CustomBehaviourContextReceiver<BehaviourContextWithFSMBuilder<T>, Unit>
): Pair<TelegramBot, Job> { ): Pair<TelegramBot, Job> {
return telegramBot( return telegramBot(
@ -85,6 +90,7 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSMAndStartLongPolling(
defaultExceptionsHandler, defaultExceptionsHandler,
statesManager, statesManager,
presetHandlers, presetHandlers,
telegramHandlersRegistrar,
block block
) )
} }

View File

@ -44,6 +44,7 @@ kotlin {
dependencies { dependencies {
implementation kotlin('stdlib') implementation kotlin('stdlib')
api project(":tgbotapi.utils") api project(":tgbotapi.utils")
api "dev.inmo:micro_utils.handlers.common:$micro_utils_version"
} }
} }
} }

View File

@ -3,6 +3,8 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder
import dev.inmo.micro_utils.coroutines.ContextSafelyExceptionHandler import dev.inmo.micro_utils.coroutines.ContextSafelyExceptionHandler
import dev.inmo.micro_utils.coroutines.ExceptionHandler import dev.inmo.micro_utils.coroutines.ExceptionHandler
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers.DefaultTelegramHandlersRegistrar
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers.TelegramHandlersRegistrar
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.longPolling 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.startGettingOfUpdatesByLongPolling
import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
@ -30,6 +32,7 @@ suspend fun TelegramBot.buildBehaviour(
flowUpdatesFilter: FlowsUpdatesFilter = FlowsUpdatesFilter(), flowUpdatesFilter: FlowsUpdatesFilter = FlowsUpdatesFilter(),
scope: CoroutineScope = defaultCoroutineScopeProvider(), scope: CoroutineScope = defaultCoroutineScopeProvider(),
defaultExceptionsHandler: ExceptionHandler<Unit>? = null, defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
telegramHandlersRegistrar: TelegramHandlersRegistrar = DefaultTelegramHandlersRegistrar(),
block: BehaviourContextReceiver<Unit> block: BehaviourContextReceiver<Unit>
) { ) {
BehaviourContext( BehaviourContext(
@ -41,7 +44,8 @@ suspend fun TelegramBot.buildBehaviour(
it + ContextSafelyExceptionHandler(defaultExceptionsHandler) it + ContextSafelyExceptionHandler(defaultExceptionsHandler)
} }
}, },
flowUpdatesFilter flowUpdatesFilter,
telegramHandlersRegistrar
).block() ).block()
} }
@ -57,12 +61,14 @@ suspend fun TelegramBot.buildBehaviour(
suspend fun TelegramBot.buildBehaviourWithLongPolling( suspend fun TelegramBot.buildBehaviourWithLongPolling(
scope: CoroutineScope = defaultCoroutineScopeProvider(), scope: CoroutineScope = defaultCoroutineScopeProvider(),
defaultExceptionsHandler: ExceptionHandler<Unit>? = null, defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
telegramHandlersRegistrar: TelegramHandlersRegistrar = DefaultTelegramHandlersRegistrar(),
block: BehaviourContextReceiver<Unit> block: BehaviourContextReceiver<Unit>
) = FlowsUpdatesFilter().let { ) = FlowsUpdatesFilter().let {
buildBehaviour( buildBehaviour(
it, it,
scope, scope,
defaultExceptionsHandler, defaultExceptionsHandler,
telegramHandlersRegistrar,
block block
) )
longPolling( longPolling(

View File

@ -4,9 +4,10 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder
import dev.inmo.micro_utils.coroutines.* import dev.inmo.micro_utils.coroutines.*
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers.DefaultTelegramHandlersRegistrar
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers.TelegramHandlersRegistrar
import dev.inmo.tgbotapi.types.update.abstracts.Update import dev.inmo.tgbotapi.types.update.abstracts.Update
import dev.inmo.tgbotapi.updateshandlers.* import dev.inmo.tgbotapi.updateshandlers.*
import dev.inmo.tgbotapi.utils.RiskFeature
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
@ -30,7 +31,7 @@ internal inline fun <BC, T, I1, I2> CustomBehaviourContextAndTwoTypesReceiver<BC
* *
* @see DefaultBehaviourContext * @see DefaultBehaviourContext
*/ */
interface BehaviourContext : FlowsUpdatesFilter, TelegramBot, CoroutineScope { interface BehaviourContext : FlowsUpdatesFilter, TelegramBot, CoroutineScope, TelegramHandlersRegistrar {
val bot: TelegramBot val bot: TelegramBot
get() = this get() = this
@ -47,12 +48,16 @@ interface BehaviourContext : FlowsUpdatesFilter, TelegramBot, CoroutineScope {
val flowsUpdatesFilter: FlowsUpdatesFilter val flowsUpdatesFilter: FlowsUpdatesFilter
get() = this get() = this
val telegramHandlersRegistrar: TelegramHandlersRegistrar
get() = this
fun copy( fun copy(
bot: TelegramBot = this.bot, bot: TelegramBot = this.bot,
scope: CoroutineScope = this.scope, scope: CoroutineScope = this.scope,
broadcastChannelsSize: Int = 100, broadcastChannelsSize: Int = 100,
onBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND, onBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND,
upstreamUpdatesFlow: Flow<Update>? = null, upstreamUpdatesFlow: Flow<Update>? = null,
telegramHandlersRegistrar: TelegramHandlersRegistrar = this.telegramHandlersRegistrar,
updatesFilter: BehaviourContextAndTypeReceiver<Boolean, Update>? = null updatesFilter: BehaviourContextAndTypeReceiver<Boolean, Update>? = null
): BehaviourContext ): BehaviourContext
} }
@ -60,11 +65,16 @@ interface BehaviourContext : FlowsUpdatesFilter, TelegramBot, CoroutineScope {
class DefaultBehaviourContext( class DefaultBehaviourContext(
override val bot: TelegramBot, override val bot: TelegramBot,
override val scope: CoroutineScope, override val scope: CoroutineScope,
override val telegramHandlersRegistrar: TelegramHandlersRegistrar,
broadcastChannelsSize: Int = 100, broadcastChannelsSize: Int = 100,
onBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND, onBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND,
private val upstreamUpdatesFlow: Flow<Update>? = null, private val upstreamUpdatesFlow: Flow<Update>? = null,
private val updatesFilter: BehaviourContextAndTypeReceiver<Boolean, Update>? = null private val updatesFilter: BehaviourContextAndTypeReceiver<Boolean, Update>? = null
) : AbstractFlowsUpdatesFilter(), TelegramBot by bot, CoroutineScope by scope, BehaviourContext { ) : AbstractFlowsUpdatesFilter(),
TelegramBot by bot,
CoroutineScope by scope,
TelegramHandlersRegistrar by telegramHandlersRegistrar,
BehaviourContext {
private val additionalUpdatesSharedFlow = MutableSharedFlow<Update>(0, broadcastChannelsSize, onBufferOverflow) private val additionalUpdatesSharedFlow = MutableSharedFlow<Update>(0, broadcastChannelsSize, onBufferOverflow)
override val allUpdatesFlow: Flow<Update> = (additionalUpdatesSharedFlow.asSharedFlow()).let { override val allUpdatesFlow: Flow<Update> = (additionalUpdatesSharedFlow.asSharedFlow()).let {
@ -89,22 +99,25 @@ class DefaultBehaviourContext(
broadcastChannelsSize: Int, broadcastChannelsSize: Int,
onBufferOverflow: BufferOverflow, onBufferOverflow: BufferOverflow,
upstreamUpdatesFlow: Flow<Update>?, upstreamUpdatesFlow: Flow<Update>?,
telegramHandlersRegistrar: TelegramHandlersRegistrar,
updatesFilter: BehaviourContextAndTypeReceiver<Boolean, Update>? updatesFilter: BehaviourContextAndTypeReceiver<Boolean, Update>?
): BehaviourContext = DefaultBehaviourContext(bot, scope, broadcastChannelsSize, onBufferOverflow, upstreamUpdatesFlow, updatesFilter) ): BehaviourContext = DefaultBehaviourContext(bot, scope, telegramHandlersRegistrar, broadcastChannelsSize, onBufferOverflow, upstreamUpdatesFlow, updatesFilter)
} }
fun BehaviourContext( fun BehaviourContext(
bot: TelegramBot, bot: TelegramBot,
scope: CoroutineScope, scope: CoroutineScope,
flowsUpdatesFilter: FlowsUpdatesFilter = FlowsUpdatesFilter() flowsUpdatesFilter: FlowsUpdatesFilter = FlowsUpdatesFilter(),
) = DefaultBehaviourContext(bot, scope, upstreamUpdatesFlow = flowsUpdatesFilter.allUpdatesFlow) telegramHandlersRegistrar: TelegramHandlersRegistrar = DefaultTelegramHandlersRegistrar(),
) = DefaultBehaviourContext(bot, scope, telegramHandlersRegistrar, upstreamUpdatesFlow = flowsUpdatesFilter.allUpdatesFlow)
inline fun <T> BehaviourContext( inline fun <T> BehaviourContext(
bot: TelegramBot, bot: TelegramBot,
scope: CoroutineScope, scope: CoroutineScope,
flowsUpdatesFilter: FlowsUpdatesFilter = FlowsUpdatesFilter(), flowsUpdatesFilter: FlowsUpdatesFilter = FlowsUpdatesFilter(),
telegramHandlersRegistrar: TelegramHandlersRegistrar = DefaultTelegramHandlersRegistrar(),
crossinline block: BehaviourContext.() -> T crossinline block: BehaviourContext.() -> T
) = DefaultBehaviourContext(bot, scope, upstreamUpdatesFlow = flowsUpdatesFilter.allUpdatesFlow).run(block) ) = DefaultBehaviourContext(bot, scope, telegramHandlersRegistrar, upstreamUpdatesFlow = flowsUpdatesFilter.allUpdatesFlow).run(block)
/** /**
* Creates new one [BehaviourContext], adding subsequent [FlowsUpdatesFilter] in case [updatesFilter] is provided and * Creates new one [BehaviourContext], adding subsequent [FlowsUpdatesFilter] in case [updatesFilter] is provided and

View File

@ -4,6 +4,8 @@ import dev.inmo.micro_utils.coroutines.ExceptionHandler
import dev.inmo.tgbotapi.bot.Ktor.KtorRequestsExecutorBuilder import dev.inmo.tgbotapi.bot.Ktor.KtorRequestsExecutorBuilder
import dev.inmo.tgbotapi.bot.Ktor.telegramBot import dev.inmo.tgbotapi.bot.Ktor.telegramBot
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers.DefaultTelegramHandlersRegistrar
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers.TelegramHandlersRegistrar
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.startGettingOfUpdatesByLongPolling import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.startGettingOfUpdatesByLongPolling
import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl
@ -30,6 +32,7 @@ suspend fun telegramBotWithBehaviour(
apiUrl: String = telegramBotAPIDefaultUrl, apiUrl: String = telegramBotAPIDefaultUrl,
builder: KtorRequestsExecutorBuilder.() -> Unit = {}, builder: KtorRequestsExecutorBuilder.() -> Unit = {},
defaultExceptionsHandler: ExceptionHandler<Unit>? = null, defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
telegramHandlersRegistrar: TelegramHandlersRegistrar = DefaultTelegramHandlersRegistrar(),
block: BehaviourContextReceiver<Unit> block: BehaviourContextReceiver<Unit>
): TelegramBot = telegramBot( ): TelegramBot = telegramBot(
token, token,
@ -40,6 +43,7 @@ suspend fun telegramBotWithBehaviour(
flowsUpdatesFilter, flowsUpdatesFilter,
scope ?: CoroutineScope(coroutineContext), scope ?: CoroutineScope(coroutineContext),
defaultExceptionsHandler, defaultExceptionsHandler,
telegramHandlersRegistrar,
block block
) )
} }
@ -63,6 +67,7 @@ suspend fun telegramBotWithBehaviourAndLongPolling(
apiUrl: String = telegramBotAPIDefaultUrl, apiUrl: String = telegramBotAPIDefaultUrl,
builder: KtorRequestsExecutorBuilder.() -> Unit = {}, builder: KtorRequestsExecutorBuilder.() -> Unit = {},
defaultExceptionsHandler: ExceptionHandler<Unit>? = null, defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
telegramHandlersRegistrar: TelegramHandlersRegistrar = DefaultTelegramHandlersRegistrar(),
block: BehaviourContextReceiver<Unit> block: BehaviourContextReceiver<Unit>
): Pair<TelegramBot, Job> { ): Pair<TelegramBot, Job> {
return telegramBot( return telegramBot(
@ -73,6 +78,7 @@ suspend fun telegramBotWithBehaviourAndLongPolling(
it to it.buildBehaviourWithLongPolling( it to it.buildBehaviourWithLongPolling(
scope ?: CoroutineScope(coroutineContext), scope ?: CoroutineScope(coroutineContext),
defaultExceptionsHandler, defaultExceptionsHandler,
telegramHandlersRegistrar,
block block
) )
} }

View File

@ -7,7 +7,6 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.CallbackQueryFilte
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByUserCallbackQueryMarkerFactory import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByUserCallbackQueryMarkerFactory
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus
import dev.inmo.tgbotapi.extensions.utils.asCallbackQueryUpdate import dev.inmo.tgbotapi.extensions.utils.asCallbackQueryUpdate
import dev.inmo.tgbotapi.types.CallbackQuery.* import dev.inmo.tgbotapi.types.CallbackQuery.*
import dev.inmo.tgbotapi.types.update.abstracts.Update import dev.inmo.tgbotapi.types.update.abstracts.Update
@ -45,62 +44,6 @@ suspend fun <BC : BehaviourContext> BC.onDataCallbackQuery(
scenarioReceiver scenarioReceiver
) )
/**
* @param dataRegex Will be used with [initialFilter] as [initialFilter] for upstream [onDataCallbackQuery] to filter
* [DataCallbackQuery] with [DataCallbackQuery.data] [String.matches] to [dataRegex]
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun <BC : BehaviourContext> BC.onDataCallbackQuery(
dataRegex: Regex,
initialFilter: SimpleFilter<DataCallbackQuery>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, DataCallbackQuery, Update>? = CallbackQueryFilterByUser,
markerFactory: MarkerFactory<in DataCallbackQuery, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, DataCallbackQuery>
) = onDataCallbackQuery(
initialFilter = initialFilter + {
it.data.matches(dataRegex)
},
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param data Will be converted to [Regex] via its constructor and pass it to upstream [onDataCallbackQuery]
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun <BC : BehaviourContext> BC.onDataCallbackQuery(
data: String,
initialFilter: SimpleFilter<DataCallbackQuery>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, DataCallbackQuery, Update>? = CallbackQueryFilterByUser,
markerFactory: MarkerFactory<in DataCallbackQuery, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, DataCallbackQuery>
) = onDataCallbackQuery(
Regex(data),
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/** /**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call * @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example, * @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
@ -173,62 +116,6 @@ suspend fun <BC : BehaviourContext> BC.onInlineMessageIdDataCallbackQuery(
scenarioReceiver scenarioReceiver
) )
/**
* @param dataRegex Will be used with [initialFilter] as [initialFilter] for upstream [onInlineMessageIdDataCallbackQuery]
* to filter [InlineMessageIdDataCallbackQuery] with [InlineMessageIdDataCallbackQuery.data] [String.matches] to [dataRegex]
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun <BC : BehaviourContext> BC.onInlineMessageIdDataCallbackQuery(
dataRegex: Regex,
initialFilter: SimpleFilter<InlineMessageIdDataCallbackQuery>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, InlineMessageIdDataCallbackQuery, Update>? = CallbackQueryFilterByUser,
markerFactory: MarkerFactory<in InlineMessageIdDataCallbackQuery, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, InlineMessageIdDataCallbackQuery>
) = onInlineMessageIdDataCallbackQuery(
initialFilter = initialFilter + {
it.data.matches(dataRegex)
},
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param data Will be converted to [Regex] via its constructor and pass it to upstream [onInlineMessageIdDataCallbackQuery]
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun <BC : BehaviourContext> BC.onInlineMessageIdDataCallbackQuery(
data: String,
initialFilter: SimpleFilter<InlineMessageIdDataCallbackQuery>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, InlineMessageIdDataCallbackQuery, Update>? = CallbackQueryFilterByUser,
markerFactory: MarkerFactory<in InlineMessageIdDataCallbackQuery, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, InlineMessageIdDataCallbackQuery>
) = onInlineMessageIdDataCallbackQuery(
Regex(data),
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/** /**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call * @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example, * @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
@ -301,62 +188,6 @@ suspend fun <BC : BehaviourContext> BC.onMessageDataCallbackQuery(
scenarioReceiver scenarioReceiver
) )
/**
* @param dataRegex Will be used with [initialFilter] as [initialFilter] for upstream [onMessageDataCallbackQuery] to filter
* [MessageDataCallbackQuery] with [MessageDataCallbackQuery.data] [String.matches] to [dataRegex]
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun <BC : BehaviourContext> BC.onMessageDataCallbackQuery(
dataRegex: Regex,
initialFilter: SimpleFilter<MessageDataCallbackQuery>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, MessageDataCallbackQuery, Update>? = CallbackQueryFilterByUser,
markerFactory: MarkerFactory<in MessageDataCallbackQuery, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, MessageDataCallbackQuery>
) = onMessageDataCallbackQuery(
initialFilter = initialFilter + {
it.data.matches(dataRegex)
},
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param data Will be converted to [Regex] via its constructor and pass it to upstream [onMessageDataCallbackQuery]
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun <BC : BehaviourContext> BC.onMessageDataCallbackQuery(
data: String,
initialFilter: SimpleFilter<MessageDataCallbackQuery>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, MessageDataCallbackQuery, Update>? = CallbackQueryFilterByUser,
markerFactory: MarkerFactory<in MessageDataCallbackQuery, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, MessageDataCallbackQuery>
) = onMessageDataCallbackQuery(
Regex(data),
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/** /**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call * @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example, * @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,

View File

@ -28,20 +28,16 @@ fun <T> SimpleFilter<T>.listNone() = SimpleFilter<Iterable<T>> {
/** /**
* Makes an AND (&&) operation between [this] and [other] * Makes an AND (&&) operation between [this] and [other]
*/ */
operator fun <T> SimpleFilter<T>?.times(other: SimpleFilter<T>): SimpleFilter<T> = this ?.let { operator fun <T> SimpleFilter<T>.times(other: SimpleFilter<T>): SimpleFilter<T> = {
{
this(it) && other(it) this(it) && other(it)
} }
} ?: other
/** /**
* Makes an OR (||) operation between [this] and [other] * Makes an OR (||) operation between [this] and [other]
*/ */
operator fun <T> SimpleFilter<T>?.plus(other: SimpleFilter<T>): SimpleFilter<T> = this ?.let { operator fun <T> SimpleFilter<T>.plus(other: SimpleFilter<T>): SimpleFilter<T> = {
{
this(it) || other(it) this(it) || other(it)
} }
} ?: other
/** /**
* Reverse results of [this] * Reverse results of [this]

View File

@ -0,0 +1,51 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers
import dev.inmo.micro_utils.handlers.common.HandlersRegistrar
import dev.inmo.tgbotapi.types.update.abstracts.Update
class DefaultTelegramHandlersRegistrar : TelegramUpdateHandler, TelegramHandlersRegistrar {
private val mainLayer = mutableListOf<TelegramUpdateHandler>()
private val defaultsLayer = mutableListOf<TelegramUpdateHandler>()
private var defaultHandler: TelegramUpdateHandler? = null
private val handlersRegistrar = HandlersRegistrar(
listOf(
mainLayer,
defaultsLayer
),
object : TelegramUpdateHandler {
override suspend fun check(data: Update): Boolean = defaultHandler ?.check(data) ?: false
override suspend fun handle(data: Update) { defaultHandler ?.handle(data) }
}
)
override suspend fun check(data: Update): Boolean {
return handlersRegistrar.check(data)
}
override suspend fun handle(data: Update) {
handlersRegistrar.handle(data)
}
override suspend fun includeHandler(handler: TelegramUpdateHandler) {
if (handler in mainLayer) {
return
}
mainLayer.add(handler)
}
override suspend fun excludeHandler(handler: TelegramUpdateHandler) {
mainLayer.remove(handler)
}
override suspend fun includeDefaultHandler(handler: TelegramUpdateHandler) {
if (handler in defaultsLayer) {
return
}
defaultsLayer.add(handler)
}
override suspend fun excludeDefaultHandler(handler: TelegramUpdateHandler) {
defaultsLayer.remove(handler)
}
}

View File

@ -0,0 +1,9 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers
interface TelegramHandlersRegistrar {
suspend fun includeHandler(handler: TelegramUpdateHandler)
suspend fun excludeHandler(handler: TelegramUpdateHandler)
suspend fun includeDefaultHandler(handler: TelegramUpdateHandler)
suspend fun excludeDefaultHandler(handler: TelegramUpdateHandler)
}

View File

@ -0,0 +1,6 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers
import dev.inmo.micro_utils.handlers.common.Handler
import dev.inmo.tgbotapi.types.update.abstracts.Update
interface TelegramUpdateHandler : Handler<Update>