diff --git a/CHANGELOG.md b/CHANGELOG.md index e47e109eb9..4a19c868f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # TelegramBotAPI changelog +## 0.35.9 + +* `Common`: + * `Version`: + * `Kotlin`: `1.5.30` -> `1.5.31` + * `Klock`: `2.4.1` -> `2.4.2` + * `MicroUtils`: `0.5.25` -> `0.5.28` +* `Core`: + * New `BotAction` implementation - `CustomBotAction` + * `LocationContent` has been divided to two different types: `LiveLocationContent` and `StaticLocationContent` +* `API`: + * Two new extensions: `TelegramBot#answer` with `CallbackQuery` and `InlineQuery` +* `Behaviour Builder`: + * All triggers have been changed to use two filters: filter for in subcontext data and filter for incoming data + * New waiters for edited content + * New extension `BehaviourContext#followLocation` + * New factory-functions: + * `BehaviourContextReceiver` + * `BehaviourContextAndTypeReceiver` + * `BehaviourContextAndTwoTypesReceiver` + * Old API for triggers with the flags like `includeFilterByChatInBehaviourSubContext` have been deprecated + ## 0.35.8 * `Common`: diff --git a/docs/gradle.properties b/docs/gradle.properties index ffe27b79a8..f0f52e73e4 100644 --- a/docs/gradle.properties +++ b/docs/gradle.properties @@ -1,3 +1,3 @@ -dokka_version=1.5.0 +dokka_version=1.5.30 org.gradle.jvmargs=-Xmx1024m diff --git a/gradle.properties b/gradle.properties index b6933b5929..fdb5b4b8bc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,18 +5,18 @@ kotlin.js.generate.externals=true kotlin.incremental=true kotlin.incremental.js=true -kotlin_version=1.5.30 +kotlin_version=1.5.31 kotlin_coroutines_version=1.5.2 kotlin_serialisation_runtime_version=1.2.2 -klock_version=2.4.1 +klock_version=2.4.2 uuid_version=0.3.1 ktor_version=1.6.3 -micro_utils_version=0.5.25 +micro_utils_version=0.5.28 javax_activation_version=1.1.1 library_group=dev.inmo -library_version=0.35.8 +library_version=0.35.9 github_release_plugin_version=2.2.12 diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/SendLocation.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/SendLocation.kt index 69da7631dc..9d564a92f9 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/SendLocation.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/send/SendLocation.kt @@ -6,7 +6,7 @@ import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass -import dev.inmo.tgbotapi.types.message.content.LocationContent +import dev.inmo.tgbotapi.types.message.content.* import dev.inmo.tgbotapi.utils.throwRangeError import kotlinx.serialization.* diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/actions/BotAction.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/actions/BotAction.kt index b258aeacf4..8abad36be6 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/actions/BotAction.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/actions/BotAction.kt @@ -1,5 +1,7 @@ package dev.inmo.tgbotapi.types.actions +import dev.inmo.micro_utils.common.Warning +import dev.inmo.tgbotapi.utils.RiskFeature import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializable import kotlinx.serialization.builtins.serializer @@ -34,7 +36,7 @@ object BotActionSerializer: KSerializer { FindLocationAction.actionName -> FindLocationAction RecordVideoNoteAction.actionName -> RecordVideoNoteAction UploadVideoNoteAction.actionName -> UploadVideoNoteAction - else -> throw IllegalStateException("Unknown action type: $actionName") + else -> CustomBotAction(actionName) } } } @@ -148,3 +150,9 @@ object UploadVideoNoteAction : BotAction { inline val uploadVideoNote get() = UploadVideoNoteAction inline fun BotAction.asUploadVideoNote() = this as? UploadVideoNoteAction + +@Serializable(BotActionSerializer::class) +@Warning("Use this action only in case you are pretty sure that there are no other action for your needs") +class CustomBotAction @RiskFeature("Usage of this action may lead to errors") constructor( + override val actionName: String +) : BotAction diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/location/Location.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/location/Location.kt index b0fcab5fd2..cefedd5189 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/location/Location.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/location/Location.kt @@ -10,6 +10,13 @@ import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.json.JsonNull import kotlinx.serialization.json.JsonObject +/** + * Common interface for any known telegram location. Use [LocationSerializer] in case you wish + * to serialize/deserialize [Location] + * + * @see dev.inmo.tgbotapi.extensions.utils.asStaticLocation + * @see dev.inmo.tgbotapi.extensions.utils.asLiveLocation + */ @Serializable(LocationSerializer::class) sealed interface Location : Locationed, HorizontallyAccured diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/LocationContent.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/LocationContent.kt index 36c5d90f35..628ffe55d2 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/LocationContent.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/content/LocationContent.kt @@ -3,46 +3,143 @@ package dev.inmo.tgbotapi.types.message.content import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.requests.send.SendLiveLocation import dev.inmo.tgbotapi.requests.send.SendStaticLocation +import dev.inmo.tgbotapi.requests.send.abstracts.SendMessageRequest import dev.inmo.tgbotapi.types.ChatIdentifier import dev.inmo.tgbotapi.types.MessageIdentifier import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup import dev.inmo.tgbotapi.types.location.* import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent -import kotlinx.serialization.Serializable +import kotlinx.serialization.* +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.descriptors.buildClassSerialDescriptor +import kotlinx.serialization.encoding.* -@Serializable -data class LocationContent( +/** + * [MessageContent] with [location]. This interface contains [copy] method for cases when you do not want to use some + * class casts for copying of content + * + * @see LocationContentSerializer + * @see Location + */ +@Serializable(LocationContentSerializer::class) +sealed interface LocationContent : MessageContent { val location: Location -) : MessageContent { + + fun copy(location: Location = this.location) { + when (this) { + is LiveLocationContent -> LiveLocationContent( + (location as? LiveLocation) ?: this.location.copy( + longitude = location.longitude, + latitude = location.latitude, + horizontalAccuracy = location.horizontalAccuracy + ) + ) + is StaticLocationContent -> StaticLocationContent( + (location as? StaticLocation) ?: this.location.copy( + longitude = location.longitude, + latitude = location.latitude, + horizontalAccuracy = location.horizontalAccuracy + ) + ) + } + } + + companion object { + operator fun invoke(location: Location): LocationContent { + return when (location) { + is StaticLocation -> StaticLocationContent(location) + is LiveLocation -> LiveLocationContent(location) + } + } + } +} + +/** + * [KSerializer] for [LocationContent] + */ +@Serializer(LocationContent::class) +object LocationContentSerializer : KSerializer { + override val descriptor: SerialDescriptor = buildClassSerialDescriptor("LocationContent") { + element(LocationContent::location.name, LocationSerializer.descriptor) + } + + override fun deserialize(decoder: Decoder): LocationContent { + lateinit var location: Location + + decoder.decodeStructure(descriptor) { + while (true) { + when (val index = decodeElementIndex(descriptor)) { + 0 -> location = decodeSerializableElement(descriptor, index, LocationSerializer) + CompositeDecoder.DECODE_DONE -> break + else -> error("Unexpected index: $index") + } + } + } + + return LocationContent(location) + } + + override fun serialize(encoder: Encoder, value: LocationContent) { + encoder.beginStructure(descriptor).apply { + encodeSerializableElement(descriptor, 0, LocationSerializer, value.location) + }.endStructure(descriptor) + } + +} + +/** + * [LocationContent] which represents content with [LiveLocation]. In case you are tracking this content throw message + * changes, may evolve to [StaticLocationContent] + * + * @see dev.inmo.tgbotapi.extensions.behaviour_builder.utils.followLocation + */ +@Serializable(LocationContentSerializer::class) +data class LiveLocationContent( + override val location: LiveLocation +) : LocationContent { override fun createResend( chatId: ChatIdentifier, disableNotification: Boolean, replyToMessageId: MessageIdentifier?, allowSendingWithoutReply: Boolean?, replyMarkup: KeyboardMarkup? - ): Request> = when (location) { - is StaticLocation -> SendStaticLocation( - chatId, - location.latitude, - location.longitude, - disableNotification, - replyToMessageId, - allowSendingWithoutReply, - replyMarkup - ) - is LiveLocation -> SendLiveLocation( - chatId, - location.latitude, - location.longitude, - location.livePeriod, - location.horizontalAccuracy, - location.heading, - location.proximityAlertRadius, - disableNotification, - replyToMessageId, - allowSendingWithoutReply, - replyMarkup - ) - } -} \ No newline at end of file + ): Request> = SendLiveLocation( + chatId, + location.latitude, + location.longitude, + location.livePeriod, + location.horizontalAccuracy, + location.heading, + location.proximityAlertRadius, + disableNotification, + replyToMessageId, + allowSendingWithoutReply, + replyMarkup + ) as SendMessageRequest> +} + +/** + * Just a [LocationContent] with [StaticLocation] [location]. It could be [LiveLocationContent] in previous time in case + * when somebody has sent [LiveLocation] in chat and then stop to broadcast location + */ +@Serializable(LocationContentSerializer::class) +data class StaticLocationContent( + override val location: StaticLocation +) : LocationContent { + override fun createResend( + chatId: ChatIdentifier, + disableNotification: Boolean, + replyToMessageId: MessageIdentifier?, + allowSendingWithoutReply: Boolean?, + replyMarkup: KeyboardMarkup? + ): Request> = SendStaticLocation( + chatId, + location.latitude, + location.longitude, + disableNotification, + replyToMessageId, + allowSendingWithoutReply, + replyMarkup + ) as SendMessageRequest> +} diff --git a/tgbotapi.core/src/commonTest/kotlin/dev/inmo/tgbotapi/types/BotActionTests.kt b/tgbotapi.core/src/commonTest/kotlin/dev/inmo/tgbotapi/types/BotActionTests.kt index e10fef23e7..451b36d9a1 100644 --- a/tgbotapi.core/src/commonTest/kotlin/dev/inmo/tgbotapi/types/BotActionTests.kt +++ b/tgbotapi.core/src/commonTest/kotlin/dev/inmo/tgbotapi/types/BotActionTests.kt @@ -27,6 +27,7 @@ class BotActionTests { FindLocationAction -> example.botAction.actionName RecordVideoNoteAction -> example.botAction.actionName UploadVideoNoteAction -> example.botAction.actionName + is CustomBotAction -> example.botAction.actionName } ) } diff --git a/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/answers/AnswerCallbackQuery.kt b/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/answers/AnswerCallbackQuery.kt index 7ccc4fc3df..ac14d1dff6 100644 --- a/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/answers/AnswerCallbackQuery.kt +++ b/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/answers/AnswerCallbackQuery.kt @@ -20,3 +20,11 @@ suspend fun TelegramBot.answerCallbackQuery( url: String? = null, cachedTimeSeconds: Int? = null ) = answerCallbackQuery(callbackQuery.id, text, showAlert, url, cachedTimeSeconds) + +suspend fun TelegramBot.answer( + callbackQuery: CallbackQuery, + text: String? = null, + showAlert: Boolean? = null, + url: String? = null, + cachedTimeSeconds: Int? = null +) = answerCallbackQuery(callbackQuery.id, text, showAlert, url, cachedTimeSeconds) diff --git a/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/answers/AnswerInlineQuery.kt b/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/answers/AnswerInlineQuery.kt index c356576c80..b40ff79f44 100644 --- a/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/answers/AnswerInlineQuery.kt +++ b/tgbotapi.extensions.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/answers/AnswerInlineQuery.kt @@ -27,3 +27,13 @@ suspend fun TelegramBot.answerInlineQuery( switchPmText: String? = null, switchPmParameter: String? = null ) = answerInlineQuery(inlineQuery.id, results, cachedTime, isPersonal, nextOffset, switchPmText, switchPmParameter) + +suspend fun TelegramBot.answer( + inlineQuery: InlineQuery, + results: List = emptyList(), + cachedTime: Int? = null, + isPersonal: Boolean? = null, + nextOffset: String? = null, + switchPmText: String? = null, + switchPmParameter: String? = null +) = answerInlineQuery(inlineQuery.id, results, cachedTime, isPersonal, nextOffset, switchPmText, switchPmParameter) diff --git a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContext.kt b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContext.kt index 35fab43c78..2fb4504b79 100644 --- a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContext.kt +++ b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContext.kt @@ -1,3 +1,5 @@ +@file:Suppress("NOTHING_TO_INLINE") + package dev.inmo.tgbotapi.extensions.behaviour_builder import dev.inmo.micro_utils.coroutines.* @@ -11,6 +13,12 @@ import kotlinx.coroutines.flow.filter typealias BehaviourContextReceiver = suspend BehaviourContext.() -> T typealias BehaviourContextAndTypeReceiver = suspend BehaviourContext.(I) -> T typealias BehaviourContextAndTwoTypesReceiver = suspend BehaviourContext.(I1, I2) -> T +inline fun BehaviourContextReceiver(noinline block: BehaviourContextReceiver) = block +inline fun BehaviourContextAndTypeReceiver(noinline block: BehaviourContextAndTypeReceiver) = block +inline fun BehaviourContextAndTwoTypesReceiver(noinline block: BehaviourContextAndTwoTypesReceiver) = block +internal inline fun BehaviourContextAndTwoTypesReceiver.toOneType( + i1: I1, +): BehaviourContextAndTypeReceiver = { invoke(this, i1, it) } /** * This class contains all necessary tools for work with bots and especially for [buildBehaviour] diff --git a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitContent.kt b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitContent.kt index 2e3063c057..d7abb32cee 100644 --- a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitContent.kt +++ b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitContent.kt @@ -51,6 +51,22 @@ private suspend fun BehaviourContext.waitCommonMessage( } }.toList().toList() +internal inline fun contentConverter( + noinline mapper: CommonMessageToContentMapper? = null +): suspend CommonMessage.() -> T? = { + if (content is T) { + @Suppress("UNCHECKED_CAST") + val message = (this as CommonMessage) + if (mapper == null) { + message.content + } else { + safelyWithoutExceptions { mapper(message) } + } + } else { + null + } +} + private suspend inline fun BehaviourContext.waitContent( count: Int = 1, initRequest: Request<*>? = null, @@ -67,20 +83,9 @@ private suspend inline fun BehaviourContext.waitCon { it.withContent() ?.let { filter(it) } == true } - } -) { - if (content is T) { - @Suppress("UNCHECKED_CAST") - val message = (this as CommonMessage) - if (mapper == null) { - message.content - } else { - safelyWithoutExceptions { mapper(message) } - } - } else { - null - } -} + }, + contentConverter(mapper) +) suspend fun BehaviourContext.waitContentMessage( initRequest: Request<*>? = null, @@ -118,6 +123,20 @@ suspend fun BehaviourContext.waitLocation( filter: SimpleFilter>? = null, mapper: CommonMessageToContentMapper? = null ) = waitContent(count, initRequest, false, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitLiveLocation( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitContent(count, initRequest, false, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitStaticLocation( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitContent(count, initRequest, false, errorFactory, filter, mapper) suspend fun BehaviourContext.waitPoll( initRequest: Request<*>? = null, errorFactory: NullableRequestBuilder<*> = { null }, diff --git a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitEditedContent.kt b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitEditedContent.kt new file mode 100644 index 0000000000..e00e832c0d --- /dev/null +++ b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/expectations/WaitEditedContent.kt @@ -0,0 +1,249 @@ +@file:Suppress("unused") + +package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations + +import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter +import dev.inmo.tgbotapi.extensions.utils.asCommonMessage +import dev.inmo.tgbotapi.extensions.utils.withContent +import dev.inmo.tgbotapi.requests.abstracts.Request +import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage +import dev.inmo.tgbotapi.types.message.abstracts.MediaGroupMessage +import dev.inmo.tgbotapi.types.message.content.* +import dev.inmo.tgbotapi.types.message.content.abstracts.* +import dev.inmo.tgbotapi.types.message.content.media.* +import dev.inmo.tgbotapi.types.message.payments.InvoiceContent +import dev.inmo.tgbotapi.types.update.abstracts.BaseEditMessageUpdate +import kotlinx.coroutines.flow.toList + +private suspend fun BehaviourContext.waitEditedCommonMessage( + count: Int = 1, + initRequest: Request<*>? = null, + includeMediaGroups: Boolean = true, + errorFactory: NullableRequestBuilder<*> = { null }, + filter: SimpleFilter>? = null, + mapper: suspend CommonMessage.() -> O? +): List = expectFlow( + initRequest, + count, + errorFactory +) { + val messages = when (it) { + is BaseEditMessageUpdate -> { + val commonMessage = it.data.asCommonMessage() + if (commonMessage !is MediaGroupMessage<*> || includeMediaGroups) { + listOf(commonMessage) + } else { + emptyList() + } + } + else -> return@expectFlow emptyList() + } + messages.mapNotNull { message -> + val asCommonMessage = message as CommonMessage + if (filter == null || filter(asCommonMessage)) { + asCommonMessage.mapper() + } else { + null + } + } +}.toList().toList() + +private suspend inline fun BehaviourContext.waitEditedContent( + count: Int = 1, + initRequest: Request<*>? = null, + includeMediaGroups: Boolean = true, + noinline errorFactory: NullableRequestBuilder<*> = { null }, + noinline filter: SimpleFilter>? = null, + noinline mapper: CommonMessageToContentMapper? = null +) : List = waitEditedCommonMessage( + count, + initRequest, + includeMediaGroups, + errorFactory, + filter ?.let { + { + it.withContent() ?.let { filter(it) } == true + } + }, + contentConverter(mapper) +) + +suspend fun BehaviourContext.waitEditedContentMessage( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + includeMediaGroups: Boolean = true, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitEditedContact( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitEditedDice( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitEditedGame( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitEditedLocation( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitEditedLiveLocation( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitEditedStaticLocation( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitEditedPoll( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitEditedText( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitEditedVenue( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitEditedAudioMediaGroupContent( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + includeMediaGroups: Boolean = true, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitEditedDocumentMediaGroupContent( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + includeMediaGroups: Boolean = true, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitEditedMedia( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + includeMediaGroups: Boolean = false, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitEditedAnyMediaGroupContent( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + includeMediaGroups: Boolean = true, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitEditedVisualMediaGroupContent( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + includeMediaGroups: Boolean = true, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitEditedAnimation( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitEditedAudio( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + includeMediaGroups: Boolean = false, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitEditedDocument( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + includeMediaGroups: Boolean = false, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitEditedPhoto( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + includeMediaGroups: Boolean = false, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitEditedSticker( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitEditedVideo( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + includeMediaGroups: Boolean = false, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitEditedVideoNote( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitEditedVoice( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper) +suspend fun BehaviourContext.waitEditedInvoice( + initRequest: Request<*>? = null, + errorFactory: NullableRequestBuilder<*> = { null }, + count: Int = 1, + filter: SimpleFilter>? = null, + mapper: CommonMessageToContentMapper? = null +) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper) diff --git a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/filters/MessageFilterByChat.kt b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/filters/MessageFilterByChat.kt new file mode 100644 index 0000000000..67c2a187d3 --- /dev/null +++ b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/filters/MessageFilterByChat.kt @@ -0,0 +1,42 @@ +package dev.inmo.tgbotapi.extensions.behaviour_builder.filters + +import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver +import dev.inmo.tgbotapi.extensions.utils.extensions.sourceChat +import dev.inmo.tgbotapi.types.CallbackQuery.CallbackQuery +import dev.inmo.tgbotapi.types.ChatMemberUpdated +import dev.inmo.tgbotapi.types.InlineQueries.query.InlineQuery +import dev.inmo.tgbotapi.types.message.abstracts.Message +import dev.inmo.tgbotapi.types.update.abstracts.Update + +/** + * Allow only events from the same chat as base [Message] + */ +val MessageFilterByChat: BehaviourContextAndTwoTypesReceiver = { message, update -> + update.sourceChat() ?.id == message.chat.id +} +/** + * Allow only events from the same chat as base [List] of [Message] + */ +val MessagesFilterByChat: BehaviourContextAndTwoTypesReceiver, Update> = { messages, update -> + val sourceChatId = update.sourceChat() ?.id + sourceChatId != null && messages.all { sourceChatId == it.chat.id } +} + +/** + * Allow only updates from the same user as base [CallbackQuery.user] + */ +val CallbackQueryFilterByUser: BehaviourContextAndTwoTypesReceiver = { query, update -> + update.sourceChat() ?.id == query.user.id +} +/** + * Allow only updates from the same user as base [InlineQuery.from] + */ +val InlineQueryFilterByUser: BehaviourContextAndTwoTypesReceiver = { query, update -> + update.sourceChat() ?.id == query.from.id +} +/** + * Allow only events from the same chat as base [ChatMemberUpdated] + */ +val ChatMemberUpdatedFilterByChat: BehaviourContextAndTwoTypesReceiver = { updated, update -> + update.sourceChat() ?.id == updated.chat.id +} diff --git a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/filters/MessageFilterExcludingMediaGroups.kt b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/filters/MessageFilterExcludingMediaGroups.kt new file mode 100644 index 0000000000..91fc62655c --- /dev/null +++ b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/filters/MessageFilterExcludingMediaGroups.kt @@ -0,0 +1,21 @@ +package dev.inmo.tgbotapi.extensions.behaviour_builder.filters + +import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver +import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.CommonMessageFilter +import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage +import dev.inmo.tgbotapi.types.message.abstracts.MediaGroupMessage +import dev.inmo.tgbotapi.types.update.abstracts.Update + +/** + * Allow only messages which are not [MediaGroupMessage] + */ +val MessageFilterExcludingMediaGroups: BehaviourContextAndTwoTypesReceiver, Update> = { message, update -> + update !is MediaGroupMessage<*> +} + +/** + * Allow only messages which are not [MediaGroupMessage] + */ +val CommonMessageFilterExcludeMediaGroups: CommonMessageFilter<*> = { + it !is MediaGroupMessage<*> +} diff --git a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/CallbackQueryTriggers.kt b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/CallbackQueryTriggers.kt index 51480d43d4..4de838699d 100644 --- a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/CallbackQueryTriggers.kt +++ b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/CallbackQueryTriggers.kt @@ -1,97 +1,346 @@ +@file:Suppress("unused") + package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling -import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptionsAsync import dev.inmo.tgbotapi.extensions.behaviour_builder.* -import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.expectFlow +import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.CallbackQueryFilterByUser 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.MarkerFactory import dev.inmo.tgbotapi.extensions.utils.asCallbackQueryUpdate -import dev.inmo.tgbotapi.extensions.utils.extensions.sourceChat import dev.inmo.tgbotapi.types.CallbackQuery.* +import dev.inmo.tgbotapi.types.update.abstracts.Update internal suspend inline fun BehaviourContext.onCallbackQuery( - includeFilterByChatInBehaviourSubContext: Boolean = true, - noinline additionalFilter: SimpleFilter? = null, + noinline initialFilter: SimpleFilter? = null, + noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver? = CallbackQueryFilterByUser, markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, noinline scenarioReceiver: BehaviourContextAndTypeReceiver -) = flowsUpdatesFilter.expectFlow(bot) { - it.asCallbackQueryUpdate() ?.data ?.let { query -> - if (query is T) { - if (additionalFilter == null || additionalFilter(query)) query else null - } else { - null - } - }.let(::listOfNotNull) -}.subscribeSafelyWithoutExceptionsAsync( - scope, - markerFactory::invoke -) { triggerQuery -> - doInSubContextWithUpdatesFilter( - updatesFilter = if (includeFilterByChatInBehaviourSubContext) { - { it.sourceChat() ?.id ?.chatId == triggerQuery.user.id.chatId } - } else { - null - }, - stopOnCompletion = false - ) { - scenarioReceiver(triggerQuery) - } +) = on(markerFactory, initialFilter, subcontextUpdatesFilter, scenarioReceiver) { + (it.asCallbackQueryUpdate() ?.data as? T) ?.let(::listOfNotNull) } - +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onDataCallbackQuery( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter? = null, markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver -) = onCallbackQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) - +) = onCallbackQuery( + additionalFilter, + if (includeFilterByChatInBehaviourSubContext) CallbackQueryFilterByUser else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onGameShortNameCallbackQuery( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter? = null, markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver -) = onCallbackQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onCallbackQuery( + additionalFilter, + if (includeFilterByChatInBehaviourSubContext) CallbackQueryFilterByUser else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onInlineMessageIdCallbackQuery( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter? = null, markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver -) = onCallbackQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onCallbackQuery( + additionalFilter, + if (includeFilterByChatInBehaviourSubContext) CallbackQueryFilterByUser else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onInlineMessageIdDataCallbackQuery( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter? = null, markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver -) = onCallbackQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onCallbackQuery( + additionalFilter, + if (includeFilterByChatInBehaviourSubContext) CallbackQueryFilterByUser else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onInlineMessageIdGameShortNameCallbackQuery( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter? = null, markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver -) = onCallbackQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onCallbackQuery( + additionalFilter, + if (includeFilterByChatInBehaviourSubContext) CallbackQueryFilterByUser else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onMessageCallbackQuery( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter? = null, markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver -) = onCallbackQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onCallbackQuery( + additionalFilter, + if (includeFilterByChatInBehaviourSubContext) CallbackQueryFilterByUser else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onMessageDataCallbackQuery( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter? = null, markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver -) = onCallbackQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onCallbackQuery( + additionalFilter, + if (includeFilterByChatInBehaviourSubContext) CallbackQueryFilterByUser else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onMessageGameShortNameCallbackQuery( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter? = null, markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver -) = onCallbackQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onCallbackQuery( + additionalFilter, + if (includeFilterByChatInBehaviourSubContext) CallbackQueryFilterByUser else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onUnknownCallbackQueryType( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter? = null, markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver -) = onCallbackQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onCallbackQuery( + additionalFilter, + if (includeFilterByChatInBehaviourSubContext) CallbackQueryFilterByUser else null, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onDataCallbackQuery( + initialFilter: SimpleFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver? = CallbackQueryFilterByUser, + markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver +) = onCallbackQuery( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onGameShortNameCallbackQuery( + initialFilter: SimpleFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver? = CallbackQueryFilterByUser, + markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver +) = onCallbackQuery( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onInlineMessageIdCallbackQuery( + initialFilter: SimpleFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver? = CallbackQueryFilterByUser, + markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver +) = onCallbackQuery( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onInlineMessageIdDataCallbackQuery( + initialFilter: SimpleFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver? = CallbackQueryFilterByUser, + markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver +) = onCallbackQuery( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onInlineMessageIdGameShortNameCallbackQuery( + initialFilter: SimpleFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver? = CallbackQueryFilterByUser, + markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver +) = onCallbackQuery( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onMessageCallbackQuery( + initialFilter: SimpleFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver? = CallbackQueryFilterByUser, + markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver +) = onCallbackQuery( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onMessageDataCallbackQuery( + initialFilter: SimpleFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver? = CallbackQueryFilterByUser, + markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver +) = onCallbackQuery( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onMessageGameShortNameCallbackQuery( + initialFilter: SimpleFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver? = CallbackQueryFilterByUser, + markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver +) = onCallbackQuery( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onUnknownCallbackQueryType( + initialFilter: SimpleFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver? = CallbackQueryFilterByUser, + markerFactory: MarkerFactory = ByUserCallbackQueryMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver +) = onCallbackQuery( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) diff --git a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ChatMemberUpdatedTriggers.kt b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ChatMemberUpdatedTriggers.kt index 6994853ec7..f6dfb202fe 100644 --- a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ChatMemberUpdatedTriggers.kt +++ b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ChatMemberUpdatedTriggers.kt @@ -1,74 +1,135 @@ +@file:Suppress("unused") + package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling -import dev.inmo.micro_utils.coroutines.subscribeSafelySkippingExceptionsAsync import dev.inmo.tgbotapi.extensions.behaviour_builder.* -import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.expectFlow +import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.ChatMemberUpdatedFilterByChat import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByChatChatMemberUpdatedMarkerFactory import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory -import dev.inmo.tgbotapi.extensions.utils.extensions.sourceChat import dev.inmo.tgbotapi.types.ChatMemberUpdated import dev.inmo.tgbotapi.types.update.CommonChatMemberUpdatedUpdate import dev.inmo.tgbotapi.types.update.MyChatMemberUpdatedUpdate import dev.inmo.tgbotapi.types.update.abstracts.ChatMemberUpdatedUpdate +import dev.inmo.tgbotapi.types.update.abstracts.Update internal suspend inline fun BehaviourContext.onChatMemberUpdatedInternal( - includeFilterByChatInBehaviourSubContext: Boolean = true, - noinline additionalFilter: SimpleFilter? = null, + noinline initialFilter: SimpleFilter? = null, + noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver? = ChatMemberUpdatedFilterByChat, markerFactory: MarkerFactory = ByChatChatMemberUpdatedMarkerFactory, noinline scenarioReceiver: BehaviourContextAndTypeReceiver -) = flowsUpdatesFilter.expectFlow(bot) { - (it as? U) ?.data ?.let { chatMemberUpdated -> - if (additionalFilter == null || additionalFilter(chatMemberUpdated)) chatMemberUpdated else null - }.let(::listOfNotNull) -}.subscribeSafelySkippingExceptionsAsync( - scope, - markerFactory::invoke -) { triggerChatMemberUpdated -> - doInSubContextWithUpdatesFilter( - updatesFilter = if (includeFilterByChatInBehaviourSubContext) { - { it.sourceChat() ?.id ?.chatId == triggerChatMemberUpdated.chat.id.chatId } - } else { - null - }, - stopOnCompletion = false - ) { - scenarioReceiver(triggerChatMemberUpdated) - } +) = on(markerFactory, initialFilter, subcontextUpdatesFilter, scenarioReceiver) { + ((it as? U) ?.data) ?.let(::listOfNotNull) } +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onChatMemberUpdated( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter? = null, markerFactory: MarkerFactory = ByChatChatMemberUpdatedMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver ) = onChatMemberUpdatedInternal( - includeFilterByChatInBehaviourSubContext, additionalFilter, + if (includeFilterByChatInBehaviourSubContext) ChatMemberUpdatedFilterByChat else null, markerFactory, scenarioReceiver ) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onCommonChatMemberUpdated( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter? = null, markerFactory: MarkerFactory = ByChatChatMemberUpdatedMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver ) = onChatMemberUpdatedInternal( - includeFilterByChatInBehaviourSubContext, additionalFilter, + if (includeFilterByChatInBehaviourSubContext) ChatMemberUpdatedFilterByChat else null, markerFactory, scenarioReceiver ) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onMyChatMemberUpdated( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter? = null, markerFactory: MarkerFactory = ByChatChatMemberUpdatedMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver ) = onChatMemberUpdatedInternal( - includeFilterByChatInBehaviourSubContext, additionalFilter, + if (includeFilterByChatInBehaviourSubContext) ChatMemberUpdatedFilterByChat else null, + markerFactory, + scenarioReceiver +) + + +/** + * @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 BehaviourContext.onChatMemberUpdated( + initialFilter: SimpleFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver? = ChatMemberUpdatedFilterByChat, + markerFactory: MarkerFactory = ByChatChatMemberUpdatedMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver +) = onChatMemberUpdatedInternal( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onCommonChatMemberUpdated( + initialFilter: SimpleFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver? = ChatMemberUpdatedFilterByChat, + markerFactory: MarkerFactory = ByChatChatMemberUpdatedMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver +) = onChatMemberUpdatedInternal( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onMyChatMemberUpdated( + initialFilter: SimpleFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver? = ChatMemberUpdatedFilterByChat, + markerFactory: MarkerFactory = ByChatChatMemberUpdatedMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver +) = onChatMemberUpdatedInternal( + initialFilter, + subcontextUpdatesFilter, markerFactory, scenarioReceiver ) diff --git a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/CommandHandling.kt b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/CommandHandling.kt index fa81c759df..6fc9e8317a 100644 --- a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/CommandHandling.kt +++ b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/CommandHandling.kt @@ -1,24 +1,31 @@ +@file:Suppress("unused") + package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling import dev.inmo.tgbotapi.extensions.behaviour_builder.* +import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.CommonMessageFilterExcludeMediaGroups +import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.MessageFilterByChat import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByChatMessageMarkerFactory import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times import dev.inmo.tgbotapi.extensions.utils.asBotCommandTextSource import dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithParams import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage import dev.inmo.tgbotapi.types.message.content.TextContent +import dev.inmo.tgbotapi.types.update.abstracts.Update import kotlinx.coroutines.Job +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.command( commandRegex: Regex, requireOnlyCommandInMessage: Boolean = true, - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> ): Job = onText( includeFilterByChatInBehaviourSubContext, - { message -> + CommonMessageFilter { message -> val content = message.content val textSources = content.textSources val sizeRequirement = if (requireOnlyCommandInMessage) { @@ -29,41 +36,47 @@ suspend fun BehaviourContext.command( sizeRequirement && textSources.any { commandRegex.matches(it.asBotCommandTextSource() ?.command ?: return@any false) } && (additionalFilter ?.invoke(message) != false) + }.let { + additionalFilter ?.times(it) ?: it }, markerFactory, scenarioReceiver ) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.command( command: String, requireOnlyCommandInMessage: Boolean = true, - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> ) = command(command.toRegex(), requireOnlyCommandInMessage, includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend inline fun BehaviourContext.onCommand( commandRegex: Regex, requireOnlyCommandInMessage: Boolean = true, - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, noinline additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, noinline scenarioReceiver: BehaviourContextAndTypeReceiver> ): Job = command(commandRegex, requireOnlyCommandInMessage, includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend inline fun BehaviourContext.onCommand( command: String, requireOnlyCommandInMessage: Boolean = true, - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, noinline additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, noinline scenarioReceiver: BehaviourContextAndTypeReceiver> ): Job = onCommand(command.toRegex(), requireOnlyCommandInMessage, includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.commandWithArgs( commandRegex: Regex, - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTwoTypesReceiver, Array> @@ -81,9 +94,10 @@ suspend fun BehaviourContext.commandWithArgs( scenarioReceiver(it, args) } +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.commandWithArgs( command: String, - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTwoTypesReceiver, Array> @@ -95,18 +109,125 @@ suspend fun BehaviourContext.commandWithArgs( scenarioReceiver = scenarioReceiver ) +@Deprecated(OldAPITriggersDeprecationText) suspend inline fun BehaviourContext.onCommandWithArgs( commandRegex: Regex, - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, noinline additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, noinline scenarioReceiver: BehaviourContextAndTwoTypesReceiver, Array> ): Job = commandWithArgs(commandRegex, includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend inline fun BehaviourContext.onCommandWithArgs( command: String, - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, noinline additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, noinline scenarioReceiver: BehaviourContextAndTwoTypesReceiver, Array> ): Job = onCommandWithArgs(command.toRegex(), includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) + + +suspend fun BehaviourContext.command( + commandRegex: Regex, + requireOnlyCommandInMessage: Boolean = true, + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +): Job = onText( + CommonMessageFilter { message -> + val content = message.content + val textSources = content.textSources + val sizeRequirement = if (requireOnlyCommandInMessage) { + textSources.size == 1 + } else { + true + } + sizeRequirement && textSources.any { + commandRegex.matches(it.asBotCommandTextSource() ?.command ?: return@any false) + } + }.let { + initialFilter ?.times(it) ?: it + }, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +suspend fun BehaviourContext.command( + command: String, + requireOnlyCommandInMessage: Boolean = true, + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = command(command.toRegex(), requireOnlyCommandInMessage, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend inline fun BehaviourContext.onCommand( + commandRegex: Regex, + requireOnlyCommandInMessage: Boolean = true, + noinline initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + noinline scenarioReceiver: BehaviourContextAndTypeReceiver> +): Job = command(commandRegex, requireOnlyCommandInMessage, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend inline fun BehaviourContext.onCommand( + command: String, + requireOnlyCommandInMessage: Boolean = true, + noinline initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + noinline scenarioReceiver: BehaviourContextAndTypeReceiver> +): Job = onCommand(command.toRegex(), requireOnlyCommandInMessage, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend fun BehaviourContext.commandWithArgs( + commandRegex: Regex, + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTwoTypesReceiver, Array> +) = command( + commandRegex, + requireOnlyCommandInMessage = false, + initialFilter = initialFilter, + subcontextUpdatesFilter = subcontextUpdatesFilter, + markerFactory = markerFactory +) { + val args = it.parseCommandsWithParams().let { commandsWithArgs -> + val key = commandsWithArgs.keys.firstOrNull { it.matches(commandRegex) } ?: return@let null + commandsWithArgs[key] + } ?: emptyArray() + scenarioReceiver(it, args) +} + +suspend fun BehaviourContext.commandWithArgs( + command: String, + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTwoTypesReceiver, Array> +) = commandWithArgs( + command.toRegex(), + initialFilter = initialFilter, + subcontextUpdatesFilter = subcontextUpdatesFilter, + markerFactory = markerFactory, + scenarioReceiver = scenarioReceiver +) + +suspend inline fun BehaviourContext.onCommandWithArgs( + commandRegex: Regex, + noinline initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + noinline scenarioReceiver: BehaviourContextAndTwoTypesReceiver, Array> +): Job = commandWithArgs(commandRegex, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +suspend inline fun BehaviourContext.onCommandWithArgs( + command: String, + noinline initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + noinline scenarioReceiver: BehaviourContextAndTwoTypesReceiver, Array> +): Job = onCommandWithArgs(command.toRegex(), initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) diff --git a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ContentTriggers.kt b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ContentTriggers.kt index 9c0d76855a..246eaccdc6 100644 --- a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ContentTriggers.kt +++ b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/ContentTriggers.kt @@ -2,194 +2,851 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling -import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptionsAsync import dev.inmo.tgbotapi.extensions.behaviour_builder.* -import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.expectFlow +import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.CommonMessageFilterExcludeMediaGroups +import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.MessageFilterByChat import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByChatMessageMarkerFactory import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory -import dev.inmo.tgbotapi.extensions.utils.* -import dev.inmo.tgbotapi.extensions.utils.extensions.sourceChat +import dev.inmo.tgbotapi.extensions.utils.whenCommonMessage import dev.inmo.tgbotapi.types.files.abstracts.TelegramMediaFile import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage import dev.inmo.tgbotapi.types.message.content.* import dev.inmo.tgbotapi.types.message.content.abstracts.* import dev.inmo.tgbotapi.types.message.content.media.* import dev.inmo.tgbotapi.types.message.payments.InvoiceContent -import dev.inmo.tgbotapi.utils.PreviewFeature +import dev.inmo.tgbotapi.types.update.MediaGroupUpdates.SentMediaGroupUpdate +import dev.inmo.tgbotapi.types.update.abstracts.BaseSentMessageUpdate +import dev.inmo.tgbotapi.types.update.abstracts.Update typealias CommonMessageFilter = SimpleFilter> +inline fun CommonMessageFilter(noinline block: CommonMessageFilter) = block -@PreviewFeature internal suspend inline fun BehaviourContext.onContent( - includeFilterByChatInBehaviourSubContext: Boolean = true, - includeMediaGroups: Boolean = true, - noinline additionalFilter: CommonMessageFilter? = null, + noinline initialFilter: CommonMessageFilter? = null, + noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, noinline scenarioReceiver: BehaviourContextAndTypeReceiver> -) = flowsUpdatesFilter.expectFlow(bot) { - val messages = it.whenBaseSentMessageUpdate { - it.data.whenCommonMessage(::listOfNotNull) - } ?: if (includeMediaGroups) { - it.asSentMediaGroupUpdate() ?.data ?: emptyList() - } else { - emptyList() - } - messages.mapNotNull { message -> - if (message.content is T) { - val adaptedMessage = message as CommonMessage - if (additionalFilter == null || additionalFilter(adaptedMessage)) adaptedMessage else null - } else { - null - } - } -}.subscribeSafelyWithoutExceptionsAsync( - scope, - markerFactory::invoke -) { triggerMessage -> - doInSubContextWithUpdatesFilter( - updatesFilter = if (includeFilterByChatInBehaviourSubContext) { - { it.sourceChat() ?.id ?.chatId == triggerMessage.chat.id.chatId } - } else { - null - }, - stopOnCompletion = false - ) { - scenarioReceiver(triggerMessage) +) = on(markerFactory, initialFilter, subcontextUpdatesFilter, scenarioReceiver) { + when (it) { + is BaseSentMessageUpdate -> it.data.whenCommonMessage(::listOfNotNull) + is SentMediaGroupUpdate -> it.data + else -> null + } ?.mapNotNull { message -> + if (message.content is T) message as CommonMessage else null } } +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onContentMessage( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: CommonMessageFilter? = null, includeMediaGroups: Boolean = true, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onContent(includeFilterByChatInBehaviourSubContext, includeMediaGroups, additionalFilter, markerFactory, scenarioReceiver) +) = onContent( + additionalFilter ?: if (includeMediaGroups) null else CommonMessageFilterExcludeMediaGroups, + if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onContact( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver) +) = onContent( + additionalFilter ?: CommonMessageFilterExcludeMediaGroups, + if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onDice( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver) +) = onContent( + additionalFilter ?: CommonMessageFilterExcludeMediaGroups, + if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onGame( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver) +) = onContent( + additionalFilter ?: CommonMessageFilterExcludeMediaGroups, + if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onLocation( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver) +) = onContent( + additionalFilter ?: CommonMessageFilterExcludeMediaGroups, + if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onPoll( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver) +) = onContent( + additionalFilter ?: CommonMessageFilterExcludeMediaGroups, + if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onText( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver) +) = onContent( + additionalFilter ?: CommonMessageFilterExcludeMediaGroups, + if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onVenue( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver) +) = onContent( + additionalFilter ?: CommonMessageFilterExcludeMediaGroups, + if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onAudioMediaGroup( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onContent(includeFilterByChatInBehaviourSubContext, true, additionalFilter, markerFactory, scenarioReceiver) +) = onContent( + additionalFilter, + if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onDocumentMediaGroupContent( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, includeMediaGroups: Boolean = true, additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onContent(includeFilterByChatInBehaviourSubContext, includeMediaGroups, additionalFilter, markerFactory, scenarioReceiver) +) = onContent( + additionalFilter ?: if (includeMediaGroups) null else CommonMessageFilterExcludeMediaGroups, + if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onMediaCollection( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, includeMediaGroups: Boolean = false, additionalFilter: SimpleFilter>>? = null, markerFactory: MarkerFactory>, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver>> -) = onContent(includeFilterByChatInBehaviourSubContext, includeMediaGroups, additionalFilter, markerFactory, scenarioReceiver) +) = onContent( + additionalFilter ?: if (includeMediaGroups) null else CommonMessageFilterExcludeMediaGroups, + if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onMedia( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, includeMediaGroups: Boolean = true, additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onContent(includeFilterByChatInBehaviourSubContext, includeMediaGroups, additionalFilter, markerFactory, scenarioReceiver) +) = onContent( + additionalFilter ?: if (includeMediaGroups) null else CommonMessageFilterExcludeMediaGroups, + if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onAnimation( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver) +) = onContent( + additionalFilter ?: CommonMessageFilterExcludeMediaGroups, + if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onAudio( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, includeMediaGroups: Boolean = false, additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onContent(includeFilterByChatInBehaviourSubContext, includeMediaGroups, additionalFilter, markerFactory, scenarioReceiver) +) = onContent( + additionalFilter ?: if (includeMediaGroups) null else CommonMessageFilterExcludeMediaGroups, + if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onDocument( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, includeMediaGroups: Boolean = false, additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onContent(includeFilterByChatInBehaviourSubContext, includeMediaGroups, additionalFilter, markerFactory, scenarioReceiver) +) = onContent( + additionalFilter ?: if (includeMediaGroups) null else CommonMessageFilterExcludeMediaGroups, + if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onPhoto( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, includeMediaGroups: Boolean = false, additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onContent(includeFilterByChatInBehaviourSubContext, includeMediaGroups, additionalFilter, markerFactory, scenarioReceiver) +) = onContent( + additionalFilter ?: if (includeMediaGroups) null else CommonMessageFilterExcludeMediaGroups, + if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onSticker( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver) +) = onContent( + additionalFilter ?: CommonMessageFilterExcludeMediaGroups, + if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onVideo( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, includeMediaGroups: Boolean = false, additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onContent(includeFilterByChatInBehaviourSubContext, includeMediaGroups, additionalFilter, markerFactory, scenarioReceiver) +) = onContent( + additionalFilter ?: if (includeMediaGroups) null else CommonMessageFilterExcludeMediaGroups, + if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onVideoNote( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver) +) = onContent( + additionalFilter ?: CommonMessageFilterExcludeMediaGroups, + if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onVoice( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver) +) = onContent( + additionalFilter ?: CommonMessageFilterExcludeMediaGroups, + if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null, + markerFactory, + scenarioReceiver +) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onInvoice( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: CommonMessageFilter? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver) +) = onContent( + additionalFilter ?: CommonMessageFilterExcludeMediaGroups, + if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null, + markerFactory, + scenarioReceiver +) + + +/** + * @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 BehaviourContext.onContentMessage( + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onContact( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onDice( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onGame( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onLocation( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onLiveLocation( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onStaticLocation( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onPoll( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onText( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onVenue( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onAudioMediaGroup( + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onDocumentMediaGroupContent( + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onMediaCollection( + initialFilter: CommonMessageFilter>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver>, Update> = MessageFilterByChat, + markerFactory: MarkerFactory>, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver>> +) = onContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onMedia( + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onAnimation( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onAudio( + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onDocument( + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onPhoto( + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onSticker( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onVideo( + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onVideoNote( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onVoice( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onInvoice( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) diff --git a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/EditedContentTriggers.kt b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/EditedContentTriggers.kt new file mode 100644 index 0000000000..c5ebda5b65 --- /dev/null +++ b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/EditedContentTriggers.kt @@ -0,0 +1,551 @@ + + +/** + * @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 + */@file:Suppress("unused", "UNCHECKED_CAST") + +package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling + +import dev.inmo.tgbotapi.extensions.behaviour_builder.* +import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.CommonMessageFilterExcludeMediaGroups +import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.MessageFilterByChat +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByChatMessageMarkerFactory +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory +import dev.inmo.tgbotapi.extensions.utils.asEditMessageUpdate +import dev.inmo.tgbotapi.extensions.utils.withContent +import dev.inmo.tgbotapi.types.files.abstracts.TelegramMediaFile +import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage +import dev.inmo.tgbotapi.types.message.content.* +import dev.inmo.tgbotapi.types.message.content.abstracts.* +import dev.inmo.tgbotapi.types.message.content.media.* +import dev.inmo.tgbotapi.types.message.payments.InvoiceContent +import dev.inmo.tgbotapi.types.update.abstracts.BaseEditMessageUpdate +import dev.inmo.tgbotapi.types.update.abstracts.Update +import dev.inmo.tgbotapi.utils.PreviewFeature + +@PreviewFeature +internal suspend inline fun BehaviourContext.onEditedContent( + noinline initialFilter: CommonMessageFilter? = null, + noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + noinline scenarioReceiver: BehaviourContextAndTypeReceiver> +) = on(markerFactory, initialFilter, subcontextUpdatesFilter, scenarioReceiver) { + when (it) { + is BaseEditMessageUpdate -> (it.asEditMessageUpdate() ?.data ?.withContent()) + else -> null + } ?.let(::listOfNotNull) +} + + +/** + * @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 BehaviourContext.onEditedContentMessage( + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +)= onEditedContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onEditedContact( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +)= onEditedContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onEditedDice( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +)= onEditedContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onEditedGame( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +)= onEditedContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onEditedLocation( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +)= onEditedContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onEditedPoll( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +)= onEditedContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onEditedText( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +)= onEditedContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onEditedVenue( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +)= onEditedContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onEditedAudioMediaGroup( + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +)= onEditedContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onEditedDocumentMediaGroupContent( + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +)= onEditedContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onEditedMediaCollection( + initialFilter: CommonMessageFilter>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver>, Update> = MessageFilterByChat, + markerFactory: MarkerFactory>, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver>> +)= onEditedContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onEditedMedia( + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +)= onEditedContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onEditedAnimation( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +)= onEditedContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onEditedAudio( + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +)= onEditedContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onEditedDocument( + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +)= onEditedContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onEditedPhoto( + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +)= onEditedContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onEditedSticker( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +)= onEditedContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onEditedVideo( + initialFilter: CommonMessageFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +)= onEditedContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onEditedVideoNote( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +)= onEditedContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onEditedVoice( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +)= onEditedContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) + +/** + * @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 BehaviourContext.onEditedInvoice( + initialFilter: CommonMessageFilter? = CommonMessageFilterExcludeMediaGroups, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update> = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +)= onEditedContent( + initialFilter, + subcontextUpdatesFilter, + markerFactory, + scenarioReceiver +) diff --git a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/EventTriggers.kt b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/EventTriggers.kt index c72c39d18d..b8fd04acc3 100644 --- a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/EventTriggers.kt +++ b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/EventTriggers.kt @@ -1,166 +1,549 @@ +@file:Suppress("unused") + package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling - -import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptionsAsync import dev.inmo.tgbotapi.extensions.behaviour_builder.* -import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.expectFlow +import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.MessageFilterByChat import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByChatMessageMarkerFactory import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory import dev.inmo.tgbotapi.extensions.utils.asBaseSentMessageUpdate import dev.inmo.tgbotapi.extensions.utils.asChatEventMessage -import dev.inmo.tgbotapi.extensions.utils.extensions.sourceChat import dev.inmo.tgbotapi.types.message.ChatEvents.* import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.* import dev.inmo.tgbotapi.types.message.ChatEvents.voice.* import dev.inmo.tgbotapi.types.message.abstracts.ChatEventMessage +import dev.inmo.tgbotapi.types.update.abstracts.Update internal suspend inline fun BehaviourContext.onEvent( - includeFilterByChatInBehaviourSubContext: Boolean = true, - noinline additionalFilter: SimpleFilter>? = null, + noinline initialFilter: SimpleFilter>? = null, + noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, noinline scenarioReceiver: BehaviourContextAndTypeReceiver> -) = flowsUpdatesFilter.expectFlow(bot) { - it.asBaseSentMessageUpdate() ?.data ?.asChatEventMessage() ?.let { message -> - if (message.chatEvent is T) { - val adaptedMessage = message as ChatEventMessage - if (additionalFilter == null || additionalFilter(adaptedMessage)) adaptedMessage else null - } else { - null - } - }.let(::listOfNotNull) -}.subscribeSafelyWithoutExceptionsAsync( - scope, - markerFactory::invoke -) { triggerMessage -> - doInSubContextWithUpdatesFilter( - updatesFilter = if (includeFilterByChatInBehaviourSubContext) { - { it.sourceChat() ?.id ?.chatId == triggerMessage.chat.id.chatId } - } else null, - stopOnCompletion = false - ) { - scenarioReceiver(triggerMessage) - } +) = on(markerFactory, initialFilter, subcontextUpdatesFilter, scenarioReceiver) { + (it.asBaseSentMessageUpdate() ?.data ?.asChatEventMessage() ?.takeIf { it.chatEvent is T } as? ChatEventMessage) ?.let(::listOfNotNull) } +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onChannelEvent( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onChatEvent( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onVoiceChatEvent( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onVoiceChatStartedEvent( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onVoiceChatEndedEvent( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onVoiceChatParticipantsInvitedEvent( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onMessageAutoDeleteTimerChangedEvent( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onCommonEvent( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onGroupEvent( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onSupergroupEvent( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onChannelChatCreated( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onDeleteChatPhoto( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onGroupChatCreated( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onLeftChatMember( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onNewChatMembers( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onNewChatPhoto( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onNewChatTitle( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onPinnedMessage( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onProximityAlertTriggered( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onSupergroupChatCreated( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>? = null, markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver> -) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver) + + + +/** + * @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 BehaviourContext.onChannelEvent( + initialFilter: SimpleFilter>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onChatEvent( + initialFilter: SimpleFilter>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onVoiceChatEvent( + initialFilter: SimpleFilter>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onVoiceChatStartedEvent( + initialFilter: SimpleFilter>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onVoiceChatEndedEvent( + initialFilter: SimpleFilter>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onVoiceChatParticipantsInvitedEvent( + initialFilter: SimpleFilter>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onMessageAutoDeleteTimerChangedEvent( + initialFilter: SimpleFilter>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onCommonEvent( + initialFilter: SimpleFilter>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onGroupEvent( + initialFilter: SimpleFilter>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onSupergroupEvent( + initialFilter: SimpleFilter>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onChannelChatCreated( + initialFilter: SimpleFilter>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onDeleteChatPhoto( + initialFilter: SimpleFilter>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onGroupChatCreated( + initialFilter: SimpleFilter>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onLeftChatMember( + initialFilter: SimpleFilter>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onNewChatMembers( + initialFilter: SimpleFilter>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onNewChatPhoto( + initialFilter: SimpleFilter>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onNewChatTitle( + initialFilter: SimpleFilter>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onPinnedMessage( + initialFilter: SimpleFilter>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onProximityAlertTriggered( + initialFilter: SimpleFilter>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onSupergroupChatCreated( + initialFilter: SimpleFilter>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver, Update>? = MessageFilterByChat, + markerFactory: MarkerFactory, Any> = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver> +) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) diff --git a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/InlineQueryTriggers.kt b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/InlineQueryTriggers.kt index 381bff6932..52567eab55 100644 --- a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/InlineQueryTriggers.kt +++ b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/InlineQueryTriggers.kt @@ -1,64 +1,105 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling -import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptionsAsync import dev.inmo.tgbotapi.extensions.behaviour_builder.* -import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.expectFlow +import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.InlineQueryFilterByUser import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByUserInlineQueryMarkerFactory import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory import dev.inmo.tgbotapi.extensions.utils.asInlineQueryUpdate -import dev.inmo.tgbotapi.extensions.utils.extensions.sourceChat import dev.inmo.tgbotapi.types.InlineQueries.query.* +import dev.inmo.tgbotapi.types.update.abstracts.Update internal suspend inline fun BehaviourContext.onInlineQuery( - includeFilterByChatInBehaviourSubContext: Boolean = true, - noinline additionalFilter: SimpleFilter? = null, + noinline initialFilter: SimpleFilter? = null, + noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver? = InlineQueryFilterByUser, markerFactory: MarkerFactory = ByUserInlineQueryMarkerFactory, noinline scenarioReceiver: BehaviourContextAndTypeReceiver -) = flowsUpdatesFilter.expectFlow(bot) { - it.asInlineQueryUpdate() ?.data ?.let { query -> - if (query is T) { - if (additionalFilter == null || additionalFilter(query)) query else null - } else { - null - } - }.let(::listOfNotNull) -}.subscribeSafelyWithoutExceptionsAsync( - scope, - markerFactory::invoke -) { triggerQuery -> - doInSubContextWithUpdatesFilter( - updatesFilter = if (includeFilterByChatInBehaviourSubContext) { - { it.sourceChat() ?.id ?.chatId == triggerQuery.from.id.chatId } - } else { - null - }, - stopOnCompletion = false - ) { - scenarioReceiver(triggerQuery) - } +) = on(markerFactory, initialFilter, subcontextUpdatesFilter, scenarioReceiver) { + (it.asInlineQueryUpdate() ?.data as? T) ?.let(::listOfNotNull) } +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onAnyInlineQuery( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter? = null, markerFactory: MarkerFactory = ByUserInlineQueryMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver -) = onInlineQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) - +) = onInlineQuery(additionalFilter, if (includeFilterByChatInBehaviourSubContext) InlineQueryFilterByUser else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onBaseInlineQuery( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter? = null, markerFactory: MarkerFactory = ByUserInlineQueryMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver -) = onInlineQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) - +) = onInlineQuery(additionalFilter, if (includeFilterByChatInBehaviourSubContext) InlineQueryFilterByUser else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onLocationInlineQuery( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter? = null, markerFactory: MarkerFactory = ByUserInlineQueryMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver -) = onInlineQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onInlineQuery(additionalFilter, if (includeFilterByChatInBehaviourSubContext) InlineQueryFilterByUser else null, markerFactory, scenarioReceiver) + + + +/** + * @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 BehaviourContext.onAnyInlineQuery( + initialFilter: SimpleFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver? = InlineQueryFilterByUser, + markerFactory: MarkerFactory = ByUserInlineQueryMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver +) = onInlineQuery(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + + +/** + * @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 BehaviourContext.onBaseInlineQuery( + initialFilter: SimpleFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver? = InlineQueryFilterByUser, + markerFactory: MarkerFactory = ByUserInlineQueryMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver +) = onInlineQuery(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + + +/** + * @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 BehaviourContext.onLocationInlineQuery( + initialFilter: SimpleFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver? = InlineQueryFilterByUser, + markerFactory: MarkerFactory = ByUserInlineQueryMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver +) = onInlineQuery(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) diff --git a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/MainTrigger.kt b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/MainTrigger.kt new file mode 100644 index 0000000000..8556adc051 --- /dev/null +++ b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/MainTrigger.kt @@ -0,0 +1,33 @@ +package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling + +import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptionsAsync +import dev.inmo.tgbotapi.extensions.behaviour_builder.* +import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.expectFlow +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter +import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory +import dev.inmo.tgbotapi.types.update.abstracts.Update + +internal const val OldAPITriggersDeprecationText = "This signature of method has been deprecated. Use signature with the" + + " same name and subcontextUpdatesFilter/initialFilter instead" + +internal suspend inline fun BehaviourContext.on( + markerFactory: MarkerFactory, + noinline initialFilter: SimpleFilter? = null, + noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver? = null, + noinline scenarioReceiver: BehaviourContextAndTypeReceiver, + noinline updateToData: (Update) -> List? +) = flowsUpdatesFilter.expectFlow(bot) { + updateToData(it) ?.mapNotNull { data -> + if (initialFilter ?.invoke(data) != false) data else null + } ?: emptyList() +}.subscribeSafelyWithoutExceptionsAsync( + scope, + markerFactory::invoke +) { triggerData -> + doInSubContextWithUpdatesFilter( + updatesFilter = subcontextUpdatesFilter ?.toOneType(triggerData), + stopOnCompletion = false + ) { + scenarioReceiver(triggerData) + } +} diff --git a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/MediaGroupTriggers.kt b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/MediaGroupTriggers.kt index 305baaddd8..f402d97c0a 100644 --- a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/MediaGroupTriggers.kt +++ b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/MediaGroupTriggers.kt @@ -2,90 +2,210 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling -import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptionsAsync import dev.inmo.tgbotapi.extensions.behaviour_builder.* -import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.expectFlow +import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.MessagesFilterByChat import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByChatMediaGroupMarkerFactory import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory import dev.inmo.tgbotapi.extensions.utils.asSentMediaGroupUpdate -import dev.inmo.tgbotapi.extensions.utils.extensions.sourceChat -import dev.inmo.tgbotapi.extensions.utils.shortcuts.chat import dev.inmo.tgbotapi.types.message.abstracts.MediaGroupMessage import dev.inmo.tgbotapi.types.message.content.abstracts.* import dev.inmo.tgbotapi.types.message.content.media.PhotoContent import dev.inmo.tgbotapi.types.message.content.media.VideoContent +import dev.inmo.tgbotapi.types.update.abstracts.Update import dev.inmo.tgbotapi.utils.PreviewFeature @PreviewFeature internal suspend inline fun BehaviourContext.buildMediaGroupTrigger( - includeFilterByChatInBehaviourSubContext: Boolean = true, - noinline additionalFilter: SimpleFilter>>? = null, + noinline initialFilter: SimpleFilter>>? = null, + noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver>, Update>? = MessagesFilterByChat, markerFactory: MarkerFactory>, Any> = ByChatMediaGroupMarkerFactory, noinline scenarioReceiver: BehaviourContextAndTypeReceiver>> -) = flowsUpdatesFilter.expectFlow(bot) { update -> - update.asSentMediaGroupUpdate() ?.data ?.let { mediaGroup -> - if (mediaGroup.all { message -> message.content is T } && (additionalFilter == null || additionalFilter(mediaGroup as List>))) { - listOf(mediaGroup as List>) - } else { - null - } - } ?: emptyList() -}.subscribeSafelyWithoutExceptionsAsync( - scope, - markerFactory::invoke -) { mediaGroup -> - val mediaGroupChat = mediaGroup.chat!! - doInSubContextWithUpdatesFilter( - updatesFilter = if (includeFilterByChatInBehaviourSubContext) { - { it.sourceChat() ?.id ?.chatId == mediaGroupChat.id.chatId } - } else null, - stopOnCompletion = false - ) { - scenarioReceiver(mediaGroup) - } +) = on(markerFactory, initialFilter, subcontextUpdatesFilter, scenarioReceiver) { + (it.asSentMediaGroupUpdate() ?.data ?.takeIf { it.all { it is T } } as? List>) ?.let(::listOfNotNull) } +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onMediaGroup( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>>? = null, markerFactory: MarkerFactory>, Any> = ByChatMediaGroupMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver>> -) = buildMediaGroupTrigger(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = buildMediaGroupTrigger(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessagesFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onPlaylist( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>>? = null, markerFactory: MarkerFactory>, Any> = ByChatMediaGroupMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver>> -) = buildMediaGroupTrigger(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = buildMediaGroupTrigger(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessagesFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onDocumentsGroup( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>>? = null, markerFactory: MarkerFactory>, Any> = ByChatMediaGroupMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver>> -) = buildMediaGroupTrigger(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = buildMediaGroupTrigger(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessagesFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onVisualGallery( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>>? = null, markerFactory: MarkerFactory>, Any> = ByChatMediaGroupMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver>> -) = buildMediaGroupTrigger(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = buildMediaGroupTrigger(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessagesFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onVisualMediaGroup( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>>? = null, markerFactory: MarkerFactory>, Any> = ByChatMediaGroupMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver>> -) = onVisualGallery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = onVisualGallery(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessagesFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onPhotoGallery( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>>? = null, markerFactory: MarkerFactory>, Any> = ByChatMediaGroupMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver>> -) = buildMediaGroupTrigger(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = buildMediaGroupTrigger(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessagesFilterByChat else null, markerFactory, scenarioReceiver) +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onVideoGallery( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter>>? = null, markerFactory: MarkerFactory>, Any> = ByChatMediaGroupMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver>> -) = buildMediaGroupTrigger(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver) +) = buildMediaGroupTrigger(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessagesFilterByChat else null, markerFactory, scenarioReceiver) + + +/** + * @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 BehaviourContext.onMediaGroup( + initialFilter: SimpleFilter>>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver>, Update>? = MessagesFilterByChat, + markerFactory: MarkerFactory>, Any> = ByChatMediaGroupMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver>> +) = buildMediaGroupTrigger(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onPlaylist( + initialFilter: SimpleFilter>>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver>, Update>? = MessagesFilterByChat, + markerFactory: MarkerFactory>, Any> = ByChatMediaGroupMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver>> +) = buildMediaGroupTrigger(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onDocumentsGroup( + initialFilter: SimpleFilter>>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver>, Update>? = MessagesFilterByChat, + markerFactory: MarkerFactory>, Any> = ByChatMediaGroupMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver>> +) = buildMediaGroupTrigger(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onVisualGallery( + initialFilter: SimpleFilter>>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver>, Update>? = MessagesFilterByChat, + markerFactory: MarkerFactory>, Any> = ByChatMediaGroupMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver>> +) = buildMediaGroupTrigger(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onVisualMediaGroup( + initialFilter: SimpleFilter>>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver>, Update>? = MessagesFilterByChat, + markerFactory: MarkerFactory>, Any> = ByChatMediaGroupMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver>> +) = onVisualGallery(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onPhotoGallery( + initialFilter: SimpleFilter>>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver>, Update>? = MessagesFilterByChat, + markerFactory: MarkerFactory>, Any> = ByChatMediaGroupMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver>> +) = buildMediaGroupTrigger(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) + +/** + * @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 BehaviourContext.onVideoGallery( + initialFilter: SimpleFilter>>? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver>, Update>? = MessagesFilterByChat, + markerFactory: MarkerFactory>, Any> = ByChatMediaGroupMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver>> +) = buildMediaGroupTrigger(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) diff --git a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/PassportTriggers.kt b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/PassportTriggers.kt index ed130e4f5d..31de2cd1ba 100644 --- a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/PassportTriggers.kt +++ b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/triggers_handling/PassportTriggers.kt @@ -1,52 +1,59 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling -import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptionsAsync import dev.inmo.tgbotapi.extensions.behaviour_builder.* -import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.expectFlow +import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.MessageFilterByChat import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByChatMessageMarkerFactory import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory import dev.inmo.tgbotapi.extensions.utils.asMessageUpdate import dev.inmo.tgbotapi.extensions.utils.asPassportMessage -import dev.inmo.tgbotapi.extensions.utils.extensions.sourceChat import dev.inmo.tgbotapi.types.message.PassportMessage import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.EncryptedPassportElement +import dev.inmo.tgbotapi.types.update.abstracts.Update internal suspend inline fun BehaviourContext.onPassportMessageWith( - includeFilterByChatInBehaviourSubContext: Boolean = true, - noinline additionalFilter: SimpleFilter? = null, + noinline initialFilter: SimpleFilter? = null, + noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver? = MessageFilterByChat, markerFactory: MarkerFactory = ByChatMessageMarkerFactory, noinline scenarioReceiver: BehaviourContextAndTypeReceiver -) = flowsUpdatesFilter.expectFlow(bot) { - it.asMessageUpdate() ?.data ?.asPassportMessage() ?.let { message -> - if (message.passportData.data.any { it is T }) { - if (additionalFilter == null || additionalFilter(message)) message else null - } else { - null - } - }.let(::listOfNotNull) -}.subscribeSafelyWithoutExceptionsAsync( - scope, - markerFactory::invoke -) { triggerMessage -> - doInSubContextWithUpdatesFilter( - updatesFilter = if (includeFilterByChatInBehaviourSubContext) { - { it.sourceChat() ?.id ?.chatId == triggerMessage.chat.id.chatId } - } else null, - stopOnCompletion = false - ) { - scenarioReceiver(triggerMessage) - } +) = on(markerFactory, initialFilter, subcontextUpdatesFilter, scenarioReceiver) { + (it.asMessageUpdate() ?.data ?.asPassportMessage() ?.takeIf { it.passportData.data.any { it is T } }) ?.let(::listOfNotNull) } +@Deprecated(OldAPITriggersDeprecationText) suspend fun BehaviourContext.onPassportMessage( - includeFilterByChatInBehaviourSubContext: Boolean = true, + includeFilterByChatInBehaviourSubContext: Boolean, additionalFilter: SimpleFilter? = null, markerFactory: MarkerFactory = ByChatMessageMarkerFactory, scenarioReceiver: BehaviourContextAndTypeReceiver ) = onPassportMessageWith( - includeFilterByChatInBehaviourSubContext, additionalFilter, + if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, + markerFactory, + scenarioReceiver +) + + +/** + * @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 BehaviourContext.onPassportMessage( + initialFilter: SimpleFilter? = null, + subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver? = MessageFilterByChat, + markerFactory: MarkerFactory = ByChatMessageMarkerFactory, + scenarioReceiver: BehaviourContextAndTypeReceiver +) = onPassportMessageWith( + initialFilter, + subcontextUpdatesFilter, markerFactory, scenarioReceiver ) diff --git a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/LiveLocation.kt b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/LiveLocation.kt new file mode 100644 index 0000000000..ac5b3deaba --- /dev/null +++ b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/LiveLocation.kt @@ -0,0 +1,30 @@ +package dev.inmo.tgbotapi.extensions.behaviour_builder.utils + +import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext +import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTypeReceiver +import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitEditedLocation +import dev.inmo.tgbotapi.types.location.* +import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage +import dev.inmo.tgbotapi.types.message.content.LiveLocationContent + +/** + * Use this extension when you want to follow [LiveLocation] until it will became [StaticLocation]. This method + * is synchronous. You may use something like [kotlinx.coroutines.launch] or [kotlinx.coroutines.async] to run it + * asynchronously + */ +suspend fun BehaviourContext.followLocation( + message: ContentMessage, + onLocation: BehaviourContextAndTypeReceiver +) { + var currentLocation: Location = message.content.location + onLocation(message.content.location) + + while (currentLocation !is StaticLocation) { + currentLocation = waitEditedLocation( + filter = { + it.messageId == message.messageId && it.chat.id == message.chat.id + } + ).first().location + onLocation(currentLocation) + } +} diff --git a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/SimpleFilter.kt b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/SimpleFilter.kt index b7b7ca17e1..6383a8cbfc 100644 --- a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/SimpleFilter.kt +++ b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/SimpleFilter.kt @@ -1,3 +1,26 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.utils typealias SimpleFilter = suspend (T) -> Boolean + +inline fun SimpleFilter(noinline block: SimpleFilter) = block + +/** + * Makes an AND (&&) operation between [this] and [other] + */ +operator fun SimpleFilter.times(other: SimpleFilter): SimpleFilter = { + this(it) && other(it) +} + +/** + * Makes an OR (||) operation between [this] and [other] + */ +operator fun SimpleFilter.plus(other: SimpleFilter): SimpleFilter = { + this(it) || other(it) +} + +/** + * Reverse results of [this] + */ +operator fun SimpleFilter.not(): SimpleFilter = { + !this(it) +} diff --git a/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/SubcontextUpdatesFilterOperations.kt b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/SubcontextUpdatesFilterOperations.kt new file mode 100644 index 0000000000..422bd05950 --- /dev/null +++ b/tgbotapi.extensions.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/utils/SubcontextUpdatesFilterOperations.kt @@ -0,0 +1,29 @@ +package dev.inmo.tgbotapi.extensions.behaviour_builder.utils + +import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver +import dev.inmo.tgbotapi.types.update.abstracts.Update + +/** + * Makes an OR (||) operation between [this] and [other] + */ +operator fun (BehaviourContextAndTwoTypesReceiver).plus( + other: BehaviourContextAndTwoTypesReceiver +) = BehaviourContextAndTwoTypesReceiver { t, update -> + this@plus(t, update) || other(t, update) +} + +/** + * Makes an AND (&&) operation between [this] and [other] + */ +operator fun (BehaviourContextAndTwoTypesReceiver).times( + other: BehaviourContextAndTwoTypesReceiver +) = BehaviourContextAndTwoTypesReceiver { t, update -> + this@times(t, update) && other(t, update) +} + +/** + * Reverse results of [this] + */ +operator fun (BehaviourContextAndTwoTypesReceiver).not() = BehaviourContextAndTwoTypesReceiver { t, update -> + !this@not(t, update) +} diff --git a/tgbotapi.extensions.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ClassCasts.kt b/tgbotapi.extensions.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ClassCasts.kt index c0da943b17..5813d6b84a 100644 --- a/tgbotapi.extensions.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ClassCasts.kt +++ b/tgbotapi.extensions.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ClassCasts.kt @@ -32,6 +32,7 @@ import dev.inmo.tgbotapi.types.chat.abstracts.extended.* import dev.inmo.tgbotapi.types.dice.* import dev.inmo.tgbotapi.types.files.* import dev.inmo.tgbotapi.types.files.abstracts.* +import dev.inmo.tgbotapi.types.location.* import dev.inmo.tgbotapi.types.message.* import dev.inmo.tgbotapi.types.message.ChatEvents.* import dev.inmo.tgbotapi.types.message.ChatEvents.LeftChatMember @@ -2506,6 +2507,24 @@ inline fun ResendableContent.asLocationContent(): LocationContent? = this as? Lo @PreviewFeature inline fun ResendableContent.requireLocationContent(): LocationContent = this as LocationContent +@PreviewFeature +inline fun ResendableContent.whenLiveLocationContent(block: (LiveLocationContent) -> T) = asLiveLocationContent() ?.let(block) + +@PreviewFeature +inline fun ResendableContent.asLiveLocationContent(): LiveLocationContent? = this as? LiveLocationContent + +@PreviewFeature +inline fun ResendableContent.requireLiveLocationContent(): LiveLocationContent = this as LiveLocationContent + +@PreviewFeature +inline fun ResendableContent.whenStaticLocationContent(block: (StaticLocationContent) -> T) = asStaticLocationContent() ?.let(block) + +@PreviewFeature +inline fun ResendableContent.asStaticLocationContent(): StaticLocationContent? = this as? StaticLocationContent + +@PreviewFeature +inline fun ResendableContent.requireStaticLocationContent(): StaticLocationContent = this as StaticLocationContent + @PreviewFeature inline fun ResendableContent.whenPollContent(block: (PollContent) -> T) = asPollContent() ?.let(block) @@ -3116,3 +3135,21 @@ inline fun Any.asWithOptionalLanguageCode(): WithOptionalLanguageCode? = this as @PreviewFeature inline fun Any.requireWithOptionalLanguageCode(): WithOptionalLanguageCode = this as WithOptionalLanguageCode + +@PreviewFeature +inline fun Location.whenStaticLocation(block: (StaticLocation) -> T) = asStaticLocation() ?.let(block) + +@PreviewFeature +inline fun Location.asStaticLocation(): StaticLocation? = this as? StaticLocation + +@PreviewFeature +inline fun Location.requireStaticLocation(): StaticLocation = this as StaticLocation + +@PreviewFeature +inline fun Location.whenLiveLocation(block: (LiveLocation) -> T) = asLiveLocation() ?.let(block) + +@PreviewFeature +inline fun Location.asLiveLocation(): LiveLocation? = this as? LiveLocation + +@PreviewFeature +inline fun Location.requireLiveLocation(): LiveLocation = this as LiveLocation diff --git a/tgbotapi.extensions.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/formatting/EntitiesBuilder.kt b/tgbotapi.extensions.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/formatting/EntitiesBuilder.kt index 24f7fd1ca7..159c7ba65a 100644 --- a/tgbotapi.extensions.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/formatting/EntitiesBuilder.kt +++ b/tgbotapi.extensions.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/formatting/EntitiesBuilder.kt @@ -6,6 +6,7 @@ import dev.inmo.tgbotapi.types.MessageEntity.textsources.* import dev.inmo.tgbotapi.types.User typealias EntitiesBuilderBody = EntitiesBuilder.() -> Unit +val newLine = regular("\n") fun buildEntities(init: EntitiesBuilderBody): TextSourcesList = EntitiesBuilder().apply(init).build() @@ -59,116 +60,395 @@ class EntitiesBuilder internal constructor( } } +/** + * Add bold using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.bold] + */ inline fun EntitiesBuilder.bold(parts: TextSourcesList) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.bold(parts)) +/** + * Version of [EntitiesBuilder.bold] with new line at the end + */ +inline fun EntitiesBuilder.boldln(parts: TextSourcesList) = bold(parts) + newLine +/** + * Add bold using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.bold] + */ inline fun EntitiesBuilder.bold(noinline init: EntitiesBuilderBody) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.bold(buildEntities(init))) - -inline fun EntitiesBuilder.bold(vararg parts: TextSource) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.bold(*parts)) - +/** + * Version of [EntitiesBuilder.bold] with new line at the end + */ +inline fun EntitiesBuilder.boldln(noinline init: EntitiesBuilderBody) = bold(init) + newLine +/** + * Add bold using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.bold] + */ +inline fun EntitiesBuilder.bold(vararg parts: TextSource) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.bold(*parts)) +/** + * Version of [EntitiesBuilder.bold] with new line at the end + */ +inline fun EntitiesBuilder.boldln(vararg parts: TextSource) = bold(*parts) + newLine +/** + * Add bold using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.bold] + */ inline fun EntitiesBuilder.bold(text: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.bold(text)) +/** + * Version of [EntitiesBuilder.bold] with new line at the end + */ +inline fun EntitiesBuilder.boldln(text: String) = bold(text) + newLine -inline fun EntitiesBuilder.botCommand(command: String) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.botCommand(command)) -inline fun EntitiesBuilder.cashTag(parts: TextSourcesList) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.cashTag(parts)) +/** + * Add botCommand using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.botCommand] + */ +inline fun EntitiesBuilder.botCommand(command: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.botCommand(command)) +/** + * Version of [EntitiesBuilder.botCommand] with new line at the end + */ +inline fun EntitiesBuilder.botCommandln(command: String) = botCommand(command) + newLine + + +/** + * Add cashTag using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.cashTag] + */ +inline fun EntitiesBuilder.cashTag(parts: TextSourcesList) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.cashTag(parts)) +/** + * Version of [EntitiesBuilder.cashTag] with new line at the end + */ +inline fun EntitiesBuilder.cashTagln(parts: TextSourcesList) = cashTag(parts) + newLine +/** + * Add cashTag using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.cashTag] + */ inline fun EntitiesBuilder.cashTag(noinline init: EntitiesBuilderBody) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.cashTag(buildEntities(init))) - -inline fun EntitiesBuilder.cashTag(vararg parts: TextSource) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.cashTag(*parts)) - +/** + * Version of [EntitiesBuilder.cashTag] with new line at the end + */ +inline fun EntitiesBuilder.cashTagln(noinline init: EntitiesBuilderBody) = cashTag(init) + newLine +/** + * Add cashTag using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.cashTag] + */ +inline fun EntitiesBuilder.cashTag(vararg parts: TextSource) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.cashTag(*parts)) +/** + * Version of [EntitiesBuilder.cashTag] with new line at the end + */ +inline fun EntitiesBuilder.cashTagln(vararg parts: TextSource) = cashTag(*parts) + newLine +/** + * Add cashTag using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.cashTag] + */ inline fun EntitiesBuilder.cashTag(text: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.cashTag(text)) +/** + * Version of [EntitiesBuilder.cashTag] with new line at the end + */ +inline fun EntitiesBuilder.cashTagln(text: String) = cashTag(text) + newLine + +/** + * Add code using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.code] + */ inline fun EntitiesBuilder.code(code: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.code(code)) +/** + * Version of [EntitiesBuilder.code] with new line at the end + */ +inline fun EntitiesBuilder.codeln(code: String) = code(code) + newLine -inline fun EntitiesBuilder.email(parts: TextSourcesList) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.email(parts)) + +/** + * Add email using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.email] + */ +inline fun EntitiesBuilder.email(parts: TextSourcesList) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.email(parts)) +/** + * Version of [EntitiesBuilder.email] with new line at the end + */ +inline fun EntitiesBuilder.emailln(parts: TextSourcesList) = email(parts) + newLine +/** + * Add email using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.email] + */ inline fun EntitiesBuilder.email(noinline init: EntitiesBuilderBody) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.email(buildEntities(init))) +/** + * Version of [EntitiesBuilder.email] with new line at the end + */ +inline fun EntitiesBuilder.emailln(noinline init: EntitiesBuilderBody) = email(init) + newLine +/** + * Add email using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.email] + */ +inline fun EntitiesBuilder.email(vararg parts: TextSource) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.email(*parts)) +/** + * Version of [EntitiesBuilder.email] with new line at the end + */ +inline fun EntitiesBuilder.emailln(vararg parts: TextSource) = email(*parts) + newLine +/** + * Add email using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.email] + */ +inline fun EntitiesBuilder.email(emailAddress: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.email(emailAddress)) +/** + * Version of [EntitiesBuilder.email] with new line at the end + */ +inline fun EntitiesBuilder.emailln(emailAddress: String) = email(emailAddress) + newLine -inline fun EntitiesBuilder.email(vararg parts: TextSource) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.email(*parts)) -inline fun EntitiesBuilder.email(emailAddress: String) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.email(emailAddress)) - -inline fun EntitiesBuilder.hashtag(parts: TextSourcesList) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.hashtag(parts)) +/** + * Add hashtag using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.hashtag] + */ +inline fun EntitiesBuilder.hashtag(parts: TextSourcesList) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.hashtag(parts)) +/** + * Version of [EntitiesBuilder.hashtag] with new line at the end + */ +inline fun EntitiesBuilder.hashtagln(parts: TextSourcesList) = hashtag(parts) + newLine +/** + * Add hashtag using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.hashtag] + */ inline fun EntitiesBuilder.hashtag(noinline init: EntitiesBuilderBody) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.hashtag(buildEntities(init))) - -inline fun EntitiesBuilder.hashtag(vararg parts: TextSource) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.hashtag(*parts)) - +/** + * Version of [EntitiesBuilder.hashtag] with new line at the end + */ +inline fun EntitiesBuilder.hashtagln(noinline init: EntitiesBuilderBody) = hashtag(init) + newLine +/** + * Add hashtag using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.hashtag] + */ +inline fun EntitiesBuilder.hashtag(vararg parts: TextSource) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.hashtag(*parts)) +/** + * Version of [EntitiesBuilder.hashtag] with new line at the end + */ +inline fun EntitiesBuilder.hashtagln(vararg parts: TextSource) = hashtag(*parts) + newLine +/** + * Add hashtag using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.hashtag] + */ inline fun EntitiesBuilder.hashtag(hashtag: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.hashtag(hashtag)) +/** + * Version of [EntitiesBuilder.hashtag] with new line at the end + */ +inline fun EntitiesBuilder.hashtagln(hashtag: String) = hashtag(hashtag) + newLine -inline fun EntitiesBuilder.italic(parts: TextSourcesList) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.italic(parts)) + +/** + * Add italic using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.italic] + */ +inline fun EntitiesBuilder.italic(parts: TextSourcesList) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.italic(parts)) +/** + * Version of [EntitiesBuilder.italic] with new line at the end + */ +inline fun EntitiesBuilder.italicln(parts: TextSourcesList) = italic(parts) + newLine +/** + * Add italic using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.italic] + */ inline fun EntitiesBuilder.italic(noinline init: EntitiesBuilderBody) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.italic(buildEntities(init))) - -inline fun EntitiesBuilder.italic(vararg parts: TextSource) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.italic(*parts)) - +/** + * Version of [EntitiesBuilder.italic] with new line at the end + */ +inline fun EntitiesBuilder.italicln(noinline init: EntitiesBuilderBody) = italic(init) + newLine +/** + * Add italic using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.italic] + */ +inline fun EntitiesBuilder.italic(vararg parts: TextSource) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.italic(*parts)) +/** + * Version of [EntitiesBuilder.italic] with new line at the end + */ +inline fun EntitiesBuilder.italicln(vararg parts: TextSource) = italic(*parts) + newLine +/** + * Add italic using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.italic] + */ inline fun EntitiesBuilder.italic(text: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.italic(text)) +/** + * Version of [EntitiesBuilder.italic] with new line at the end + */ +inline fun EntitiesBuilder.italicln(text: String) = italic(text) + newLine -inline fun EntitiesBuilder.mention(parts: TextSourcesList) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(parts)) + +/** + * Add mention using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.mention] + */ +inline fun EntitiesBuilder.mention(parts: TextSourcesList) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(parts)) +/** + * Version of [EntitiesBuilder.mention] with new line at the end + */ +inline fun EntitiesBuilder.mentionln(parts: TextSourcesList) = mention(parts) + newLine +/** + * Add mention using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.mention] + */ inline fun EntitiesBuilder.mention(noinline init: EntitiesBuilderBody) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(buildEntities(init))) - -inline fun EntitiesBuilder.mention(vararg parts: TextSource) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(*parts)) - -inline fun EntitiesBuilder.mention(whoToMention: String) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(whoToMention)) - -inline fun EntitiesBuilder.mention(parts: TextSourcesList, user: User) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(parts, user)) - +/** + * Version of [EntitiesBuilder.mention] with new line at the end + */ +inline fun EntitiesBuilder.mentionln(noinline init: EntitiesBuilderBody) = mention(init) + newLine +/** + * Add mention using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.mention] + */ +inline fun EntitiesBuilder.mention(vararg parts: TextSource) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(*parts)) +/** + * Version of [EntitiesBuilder.mention] with new line at the end + */ +inline fun EntitiesBuilder.mentionln(vararg parts: TextSource) = mention(*parts) + newLine +/** + * Add mention using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.mention] + */ +inline fun EntitiesBuilder.mention(whoToMention: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(whoToMention)) +/** + * Version of [EntitiesBuilder.mention] with new line at the end + */ +inline fun EntitiesBuilder.mentionln(whoToMention: String) = mention(whoToMention) + newLine +/** + * Add mention using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.mention] + */ +inline fun EntitiesBuilder.mention(parts: TextSourcesList, user: User) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(parts, user)) +/** + * Version of [EntitiesBuilder.mention] with new line at the end + */ +inline fun EntitiesBuilder.mentionln(parts: TextSourcesList, user: User) = mention(parts) + newLine inline fun EntitiesBuilder.mention( user: User, vararg parts: TextSource -) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(user, *parts)) +) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(user, *parts)) +/** + * Version of [EntitiesBuilder.mention] with new line at the end + */ +inline fun EntitiesBuilder.mentionln(user: User, vararg parts: TextSource) = mention(user, *parts) + newLine +/** + * Add mention using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.mention] + */ +inline fun EntitiesBuilder.mention(text: String, user: User) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(text, user)) +/** + * Version of [EntitiesBuilder.mention] with new line at the end + */ +inline fun EntitiesBuilder.mentionln(text: String, user: User) = mention(text) + newLine -inline fun EntitiesBuilder.mention(text: String, user: User) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(text, user)) -inline fun EntitiesBuilder.phone(parts: TextSourcesList) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.phone(parts)) +/** + * Add phone using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.phone] + */ +inline fun EntitiesBuilder.phone(parts: TextSourcesList) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.phone(parts)) +/** + * Version of [EntitiesBuilder.phone] with new line at the end + */ +inline fun EntitiesBuilder.phoneln(parts: TextSourcesList) = phone(parts) + newLine +/** + * Add phone using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.phone] + */ inline fun EntitiesBuilder.phone(noinline init: EntitiesBuilderBody) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.phone(buildEntities(init))) +/** + * Version of [EntitiesBuilder.phone] with new line at the end + */ +inline fun EntitiesBuilder.phoneln(noinline init: EntitiesBuilderBody) = phone(init) + newLine +/** + * Add phone using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.phone] + */ +inline fun EntitiesBuilder.phone(vararg parts: TextSource) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.phone(*parts)) +/** + * Version of [EntitiesBuilder.phone] with new line at the end + */ +inline fun EntitiesBuilder.phoneln(vararg parts: TextSource) = phone(*parts) + newLine +/** + * Add phone using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.phone] + */ +inline fun EntitiesBuilder.phone(number: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.phone(number)) +/** + * Version of [EntitiesBuilder.phone] with new line at the end + */ +inline fun EntitiesBuilder.phoneln(number: String) = phone(number) + newLine -inline fun EntitiesBuilder.phone(vararg parts: TextSource) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.phone(*parts)) -inline fun EntitiesBuilder.phone(number: String) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.phone(number)) - -inline fun EntitiesBuilder.pre(code: String, language: String?) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.pre(code, language)) +/** + * Add pre using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.pre] + */ +inline fun EntitiesBuilder.pre(code: String, language: String?) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.pre(code, language)) +/** + * Version of [EntitiesBuilder.pre] with new line at the end + */ +inline fun EntitiesBuilder.preln(code: String, language: String?) = pre(code) + newLine +/** + * Will add simple [dev.inmo.tgbotapi.types.MessageEntity.textsources.regular] [TextSource] + * + * @see RegularTextSource + * @see dev.inmo.tgbotapi.extensions.utils.formatting.regularln + */ inline fun EntitiesBuilder.regular(text: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.regular(text)) +/** + * Will add simple [dev.inmo.tgbotapi.types.MessageEntity.textsources.regular] [TextSource] and "\n" at the end + * + * @see RegularTextSource + * @see dev.inmo.tgbotapi.extensions.utils.formatting.regular + */ +inline fun EntitiesBuilder.regularln(text: String) = regular(text) + newLine -inline fun EntitiesBuilder.strikethrough(parts: TextSourcesList) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.strikethrough(parts)) + +/** + * Add strikethrough using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.strikethrough] + */ +inline fun EntitiesBuilder.strikethrough(parts: TextSourcesList) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.strikethrough(parts)) +/** + * Version of [EntitiesBuilder.strikethrough] with new line at the end + */ +inline fun EntitiesBuilder.strikethroughln(parts: TextSourcesList) = strikethrough(parts) + newLine +/** + * Add strikethrough using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.strikethrough] + */ inline fun EntitiesBuilder.strikethrough(noinline init: EntitiesBuilderBody) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.strikethrough(buildEntities(init))) +/** + * Version of [EntitiesBuilder.strikethrough] with new line at the end + */ +inline fun EntitiesBuilder.strikethroughln(noinline init: EntitiesBuilderBody) = strikethrough(init) + newLine +/** + * Add strikethrough using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.strikethrough] + */ +inline fun EntitiesBuilder.strikethrough(vararg parts: TextSource) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.strikethrough(*parts)) +/** + * Version of [EntitiesBuilder.strikethrough] with new line at the end + */ +inline fun EntitiesBuilder.strikethroughln(vararg parts: TextSource) = strikethrough(*parts) + newLine +/** + * Add strikethrough using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.strikethrough] + */ +inline fun EntitiesBuilder.strikethrough(text: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.strikethrough(text)) +/** + * Version of [EntitiesBuilder.strikethrough] with new line at the end + */ +inline fun EntitiesBuilder.strikethroughln(text: String) = strikethrough(text) + newLine -inline fun EntitiesBuilder.strikethrough(vararg parts: TextSource) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.strikethrough(*parts)) -inline fun EntitiesBuilder.strikethrough(text: String) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.strikethrough(text)) +/** + * Add link using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.link] + */ +inline fun EntitiesBuilder.link(text: String, url: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.link(text, url)) +/** + * Version of [EntitiesBuilder.link] with new line at the end + */ +inline fun EntitiesBuilder.linkln(text: String, url: String) = link(text) + newLine +/** + * Add link using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.link] + */ +inline fun EntitiesBuilder.link(url: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.link(url)) +/** + * Version of [EntitiesBuilder.link] with new line at the end + */ +inline fun EntitiesBuilder.linkln(url: String) = link(url) + newLine -inline fun EntitiesBuilder.link(text: String, url: String) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.link(text, url)) -inline fun EntitiesBuilder.link(url: String) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.link(url)) - -inline fun EntitiesBuilder.underline(parts: TextSourcesList) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.underline(parts)) +/** + * Add underline using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.underline] + */ +inline fun EntitiesBuilder.underline(parts: TextSourcesList) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.underline(parts)) +/** + * Version of [EntitiesBuilder.underline] with new line at the end + */ +inline fun EntitiesBuilder.underlineln(parts: TextSourcesList) = underline(parts) + newLine +/** + * Add underline using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.underline] + */ inline fun EntitiesBuilder.underline(noinline init: EntitiesBuilderBody) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.underline(buildEntities(init))) - -inline fun EntitiesBuilder.underline(vararg parts: TextSource) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.underline(*parts)) - -inline fun EntitiesBuilder.underline(text: String) = - add(dev.inmo.tgbotapi.types.MessageEntity.textsources.underline(text)) +/** + * Version of [EntitiesBuilder.underline] with new line at the end + */ +inline fun EntitiesBuilder.underlineln(noinline init: EntitiesBuilderBody) = underline(init) + newLine +/** + * Add underline using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.underline] + */ +inline fun EntitiesBuilder.underline(vararg parts: TextSource) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.underline(*parts)) +/** + * Version of [EntitiesBuilder.underline] with new line at the end + */ +inline fun EntitiesBuilder.underlineln(vararg parts: TextSource) = underline(*parts) + newLine +/** + * Add underline using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.underline] + */ +inline fun EntitiesBuilder.underline(text: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.underline(text)) +/** + * Version of [EntitiesBuilder.underline] with new line at the end + */ +inline fun EntitiesBuilder.underlineln(text: String) = underline(text) + newLine