mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2024-12-23 00:57:13 +00:00
add callback query expectations and triggers
This commit is contained in:
parent
965b8c3c50
commit
3125c2fc1b
@ -0,0 +1,107 @@
|
||||
@file:Suppress("unused")
|
||||
|
||||
package dev.inmo.tgbotapi.extensions.steps.expectations
|
||||
|
||||
import dev.inmo.tgbotapi.extensions.steps.Scenario
|
||||
import dev.inmo.tgbotapi.extensions.utils.*
|
||||
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||
import dev.inmo.tgbotapi.types.CallbackQuery.*
|
||||
import dev.inmo.tgbotapi.types.message.ChatEvents.*
|
||||
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.*
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.ChatEventMessage
|
||||
import dev.inmo.tgbotapi.types.message.content.ContactContent
|
||||
import dev.inmo.tgbotapi.types.update.CallbackQueryUpdate
|
||||
import kotlinx.coroutines.flow.toList
|
||||
|
||||
typealias CallbackQueryMapper<T> = T.() -> T?
|
||||
|
||||
private suspend fun <O> Scenario.waitCallbackQueries(
|
||||
count: Int = 1,
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
mapper: suspend CallbackQuery.() -> O?
|
||||
): List<O> = expectFlow(
|
||||
initRequest,
|
||||
count,
|
||||
errorFactory
|
||||
) {
|
||||
it.asCallbackQueryUpdate() ?.data ?.mapper()
|
||||
}.toList().toList()
|
||||
|
||||
|
||||
private suspend inline fun <reified T : CallbackQuery> Scenario.waitEvents(
|
||||
count: Int = 1,
|
||||
initRequest: Request<*>? = null,
|
||||
noinline errorFactory: NullableRequestBuilder<*> = { null },
|
||||
noinline filter: CallbackQueryMapper<T>? = null
|
||||
) : List<T> = waitCallbackQueries<T>(
|
||||
count,
|
||||
initRequest,
|
||||
errorFactory
|
||||
) {
|
||||
if (this is T) {
|
||||
if (filter == null) {
|
||||
this
|
||||
} else {
|
||||
filter(this)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
suspend fun Scenario.waitDataCallbackQuery(
|
||||
count: Int = 1,
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
filter: CallbackQueryMapper<DataCallbackQuery>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
suspend fun Scenario.waitGameShortNameCallbackQuery(
|
||||
count: Int = 1,
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
filter: CallbackQueryMapper<GameShortNameCallbackQuery>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
suspend fun Scenario.waitInlineMessageIdCallbackQuery(
|
||||
count: Int = 1,
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
filter: CallbackQueryMapper<InlineMessageIdCallbackQuery>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
suspend fun Scenario.waitInlineMessageIdDataCallbackQuery(
|
||||
count: Int = 1,
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
filter: CallbackQueryMapper<InlineMessageIdDataCallbackQuery>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
suspend fun Scenario.waitInlineMessageIdGameShortNameCallbackQuery(
|
||||
count: Int = 1,
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
filter: CallbackQueryMapper<InlineMessageIdGameShortNameCallbackQuery>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
suspend fun Scenario.waitMessageCallbackQuery(
|
||||
count: Int = 1,
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
filter: CallbackQueryMapper<MessageCallbackQuery>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
suspend fun Scenario.waitMessageDataCallbackQuery(
|
||||
count: Int = 1,
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
filter: CallbackQueryMapper<MessageDataCallbackQuery>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
suspend fun Scenario.waitMessageGameShortNameCallbackQuery(
|
||||
count: Int = 1,
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
filter: CallbackQueryMapper<MessageGameShortNameCallbackQuery>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
suspend fun Scenario.waitUnknownCallbackQuery(
|
||||
count: Int = 1,
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
filter: CallbackQueryMapper<UnknownCallbackQueryType>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
@ -0,0 +1,91 @@
|
||||
package dev.inmo.tgbotapi.extensions.steps.triggers_handling
|
||||
|
||||
|
||||
import dev.inmo.micro_utils.coroutines.safelyWithoutExceptions
|
||||
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
||||
import dev.inmo.tgbotapi.extensions.steps.Scenario
|
||||
import dev.inmo.tgbotapi.extensions.steps.ScenarioAndTypeReceiver
|
||||
import dev.inmo.tgbotapi.extensions.steps.expectations.expectFlow
|
||||
import dev.inmo.tgbotapi.extensions.utils.*
|
||||
import dev.inmo.tgbotapi.extensions.utils.extensions.sourceChat
|
||||
import dev.inmo.tgbotapi.types.CallbackQuery.*
|
||||
import dev.inmo.tgbotapi.types.message.ChatEvents.*
|
||||
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.*
|
||||
import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
|
||||
import kotlinx.coroutines.flow.filter
|
||||
|
||||
internal suspend inline fun <reified T : CallbackQuery> Scenario.onCallbackQuery(
|
||||
includeFilterByChatInSubScenario: Boolean = true,
|
||||
noinline additionalFilter: (suspend (T) -> Boolean)? = null,
|
||||
noinline scenarioReceiver: ScenarioAndTypeReceiver<Unit, T>
|
||||
) = flowsUpdatesFilter.expectFlow(bot) {
|
||||
it.asCallbackQueryUpdate() ?.data ?.let { query ->
|
||||
if (query is T) {
|
||||
if (additionalFilter == null || additionalFilter(query)) query else null
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}.subscribeSafelyWithoutExceptions(scope) { triggerQuery ->
|
||||
val (jobToCancel, scenario) = if (includeFilterByChatInSubScenario) {
|
||||
val subFilter = FlowsUpdatesFilter()
|
||||
val subScenario = copy(flowsUpdatesFilter = subFilter)
|
||||
|
||||
flowsUpdatesFilter.allUpdatesFlow.filter {
|
||||
val chat = it.sourceChat() ?: return@filter false
|
||||
chat.id.chatId == triggerQuery.user.id.chatId
|
||||
}.subscribeSafelyWithoutExceptions(scope, subFilter.asUpdateReceiver) to subScenario
|
||||
} else {
|
||||
null to this
|
||||
}
|
||||
safelyWithoutExceptions { scenario.scenarioReceiver(triggerQuery) }
|
||||
jobToCancel ?.cancel()
|
||||
}
|
||||
|
||||
|
||||
suspend fun Scenario.onDataCallbackQuery(
|
||||
includeFilterByChatInSubScenario: Boolean = true,
|
||||
additionalFilter: (suspend (DataCallbackQuery) -> Boolean)? = null,
|
||||
scenarioReceiver: ScenarioAndTypeReceiver<Unit, DataCallbackQuery>
|
||||
) = onCallbackQuery(includeFilterByChatInSubScenario, additionalFilter, scenarioReceiver)
|
||||
|
||||
suspend fun Scenario.onGameShortNameCallbackQuery(
|
||||
includeFilterByChatInSubScenario: Boolean = true,
|
||||
additionalFilter: (suspend (GameShortNameCallbackQuery) -> Boolean)? = null,
|
||||
scenarioReceiver: ScenarioAndTypeReceiver<Unit, GameShortNameCallbackQuery>
|
||||
) = onCallbackQuery(includeFilterByChatInSubScenario, additionalFilter, scenarioReceiver)
|
||||
suspend fun Scenario.onInlineMessageIdCallbackQuery(
|
||||
includeFilterByChatInSubScenario: Boolean = true,
|
||||
additionalFilter: (suspend (InlineMessageIdCallbackQuery) -> Boolean)? = null,
|
||||
scenarioReceiver: ScenarioAndTypeReceiver<Unit, InlineMessageIdCallbackQuery>
|
||||
) = onCallbackQuery(includeFilterByChatInSubScenario, additionalFilter, scenarioReceiver)
|
||||
suspend fun Scenario.onInlineMessageIdDataCallbackQuery(
|
||||
includeFilterByChatInSubScenario: Boolean = true,
|
||||
additionalFilter: (suspend (InlineMessageIdDataCallbackQuery) -> Boolean)? = null,
|
||||
scenarioReceiver: ScenarioAndTypeReceiver<Unit, InlineMessageIdDataCallbackQuery>
|
||||
) = onCallbackQuery(includeFilterByChatInSubScenario, additionalFilter, scenarioReceiver)
|
||||
suspend fun Scenario.onInlineMessageIdGameShortNameCallbackQuery(
|
||||
includeFilterByChatInSubScenario: Boolean = true,
|
||||
additionalFilter: (suspend (InlineMessageIdGameShortNameCallbackQuery) -> Boolean)? = null,
|
||||
scenarioReceiver: ScenarioAndTypeReceiver<Unit, InlineMessageIdGameShortNameCallbackQuery>
|
||||
) = onCallbackQuery(includeFilterByChatInSubScenario, additionalFilter, scenarioReceiver)
|
||||
suspend fun Scenario.onMessageCallbackQuery(
|
||||
includeFilterByChatInSubScenario: Boolean = true,
|
||||
additionalFilter: (suspend (MessageCallbackQuery) -> Boolean)? = null,
|
||||
scenarioReceiver: ScenarioAndTypeReceiver<Unit, MessageCallbackQuery>
|
||||
) = onCallbackQuery(includeFilterByChatInSubScenario, additionalFilter, scenarioReceiver)
|
||||
suspend fun Scenario.onMessageDataCallbackQuery(
|
||||
includeFilterByChatInSubScenario: Boolean = true,
|
||||
additionalFilter: (suspend (MessageDataCallbackQuery) -> Boolean)? = null,
|
||||
scenarioReceiver: ScenarioAndTypeReceiver<Unit, MessageDataCallbackQuery>
|
||||
) = onCallbackQuery(includeFilterByChatInSubScenario, additionalFilter, scenarioReceiver)
|
||||
suspend fun Scenario.onMessageGameShortNameCallbackQuery(
|
||||
includeFilterByChatInSubScenario: Boolean = true,
|
||||
additionalFilter: (suspend (MessageGameShortNameCallbackQuery) -> Boolean)? = null,
|
||||
scenarioReceiver: ScenarioAndTypeReceiver<Unit, MessageGameShortNameCallbackQuery>
|
||||
) = onCallbackQuery(includeFilterByChatInSubScenario, additionalFilter, scenarioReceiver)
|
||||
suspend fun Scenario.onUnknownCallbackQueryType(
|
||||
includeFilterByChatInSubScenario: Boolean = true,
|
||||
additionalFilter: (suspend (UnknownCallbackQueryType) -> Boolean)? = null,
|
||||
scenarioReceiver: ScenarioAndTypeReceiver<Unit, UnknownCallbackQueryType>
|
||||
) = onCallbackQuery(includeFilterByChatInSubScenario, additionalFilter, scenarioReceiver)
|
@ -8,6 +8,7 @@ import dev.inmo.tgbotapi.extensions.steps.ScenarioAndTypeReceiver
|
||||
import dev.inmo.tgbotapi.extensions.steps.expectations.expectFlow
|
||||
import dev.inmo.tgbotapi.extensions.utils.asContentMessage
|
||||
import dev.inmo.tgbotapi.extensions.utils.asMessageUpdate
|
||||
import dev.inmo.tgbotapi.extensions.utils.extensions.sourceChat
|
||||
import dev.inmo.tgbotapi.types.files.abstracts.TelegramMediaFile
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||
import dev.inmo.tgbotapi.types.message.content.*
|
||||
@ -37,7 +38,8 @@ internal suspend inline fun <reified T : MessageContent> Scenario.onContent(
|
||||
val subScenario = copy(flowsUpdatesFilter = subFilter)
|
||||
|
||||
flowsUpdatesFilter.allUpdatesFlow.filter {
|
||||
it.asMessageUpdate() ?.data ?.let { it.chat.id.chatId == triggerMessage.chat.id.chatId } == true
|
||||
val chat = it.sourceChat() ?: return@filter false
|
||||
chat.id.chatId == triggerMessage.chat.id.chatId
|
||||
}.subscribeSafelyWithoutExceptions(scope, subFilter.asUpdateReceiver) to subScenario
|
||||
} else {
|
||||
null to this
|
||||
|
@ -7,6 +7,7 @@ import dev.inmo.tgbotapi.extensions.steps.Scenario
|
||||
import dev.inmo.tgbotapi.extensions.steps.ScenarioAndTypeReceiver
|
||||
import dev.inmo.tgbotapi.extensions.steps.expectations.expectFlow
|
||||
import dev.inmo.tgbotapi.extensions.utils.*
|
||||
import dev.inmo.tgbotapi.extensions.utils.extensions.sourceChat
|
||||
import dev.inmo.tgbotapi.types.files.abstracts.TelegramMediaFile
|
||||
import dev.inmo.tgbotapi.types.message.ChatEvents.*
|
||||
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.*
|
||||
@ -38,7 +39,8 @@ internal suspend inline fun <reified T : ChatEvent> Scenario.onEvent(
|
||||
val subScenario = copy(flowsUpdatesFilter = subFilter)
|
||||
|
||||
flowsUpdatesFilter.allUpdatesFlow.filter {
|
||||
it.asMessageUpdate() ?.data ?.let { it.chat.id.chatId == triggerMessage.chat.id.chatId } == true
|
||||
val chat = it.sourceChat() ?: return@filter false
|
||||
chat.id.chatId == triggerMessage.chat.id.chatId
|
||||
}.subscribeSafelyWithoutExceptions(scope, subFilter.asUpdateReceiver) to subScenario
|
||||
} else {
|
||||
null to this
|
||||
|
@ -0,0 +1,26 @@
|
||||
package dev.inmo.tgbotapi.extensions.utils.extensions
|
||||
|
||||
import dev.inmo.tgbotapi.extensions.utils.shortcuts.chat
|
||||
import dev.inmo.tgbotapi.types.chat.abstracts.Chat
|
||||
import dev.inmo.tgbotapi.types.update.*
|
||||
import dev.inmo.tgbotapi.types.update.MediaGroupUpdates.*
|
||||
import dev.inmo.tgbotapi.types.update.abstracts.BaseMessageUpdate
|
||||
import dev.inmo.tgbotapi.types.update.abstracts.Update
|
||||
import dev.inmo.tgbotapi.utils.PreviewFeature
|
||||
|
||||
@PreviewFeature
|
||||
fun Update.sourceChat(): Chat? = when (this) {
|
||||
is MediaGroupUpdate -> when (this) {
|
||||
is SentMediaGroupUpdate -> data.chat
|
||||
is EditMediaGroupUpdate -> data.chat
|
||||
else -> null
|
||||
}
|
||||
is BaseMessageUpdate -> data.chat
|
||||
is InlineQueryUpdate -> data.from
|
||||
is ChosenInlineResultUpdate -> data.user
|
||||
is CallbackQueryUpdate -> data.user
|
||||
is PreCheckoutQueryUpdate -> data.user
|
||||
is PollAnswerUpdate -> data.user
|
||||
is ShippingQueryUpdate -> data.user
|
||||
else -> null
|
||||
}
|
Loading…
Reference in New Issue
Block a user