1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2024-11-22 08:13:47 +00:00

several fixes

This commit is contained in:
InsanusMokrassar 2022-11-08 02:50:22 +06:00
parent f6f07a5e8a
commit 4736610aa8
12 changed files with 371 additions and 35 deletions

View File

@ -11,5 +11,5 @@ import dev.inmo.tgbotapi.types.update.abstracts.Update
* Allow only messages which are not [MediaGroupMessage] * Allow only messages which are not [MediaGroupMessage]
*/ */
val CommonMessageFilterExcludeMediaGroups = SimpleFilter<Message> { val CommonMessageFilterExcludeMediaGroups = SimpleFilter<Message> {
it !is CommonMessage<*> || it.content !is MediaGroupContent it !is CommonMessage<*> || it.content !is MediaGroupContent<*>
} }

View File

@ -0,0 +1,164 @@
@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.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.baseSentMessageUpdateOrNull
import dev.inmo.tgbotapi.extensions.utils.commonMessageOrNull
import dev.inmo.tgbotapi.extensions.utils.withContentOrNull
import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage
import dev.inmo.tgbotapi.types.message.content.*
import dev.inmo.tgbotapi.types.update.abstracts.Update
import dev.inmo.tgbotapi.utils.PreviewFeature
@PreviewFeature
internal suspend inline fun <BC : BehaviourContext, reified T : MediaGroupPartContent> BC.buildMediaGroupMessagesTrigger(
initialFilter: SimpleFilter<MediaGroupMessage<T>>? = null,
noinline subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, MediaGroupMessage<T>, Update>? = null,
markerFactory: MarkerFactory<in MediaGroupMessage<T>, Any> = ByChatMessageMarkerFactory,
noinline scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, MediaGroupMessage<T>>
) = on(markerFactory, initialFilter, subcontextUpdatesFilter, scenarioReceiver) {
it.baseSentMessageUpdateOrNull() ?.data ?.commonMessageOrNull() ?.withContentOrNull<MediaGroupContent<*>>() ?.let {
if (it.content.group.all { it.content is T }) {
listOf(it as MediaGroupMessage<T>)
} else {
null
}
} ?: emptyList()
}
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun <BC : BehaviourContext> BC.onMediaGroupMessages(
initialFilter: SimpleFilter<MediaGroupMessage<MediaGroupPartContent>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, MediaGroupMessage<MediaGroupPartContent>, Update>? = null,
markerFactory: MarkerFactory<in MediaGroupMessage<MediaGroupPartContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, MediaGroupMessage<MediaGroupPartContent>>
) = buildMediaGroupMessagesTrigger(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 <BC : BehaviourContext> BC.onPlaylistMessages(
initialFilter: SimpleFilter<MediaGroupMessage<AudioMediaGroupPartContent>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, MediaGroupMessage<AudioMediaGroupPartContent>, Update>? = null,
markerFactory: MarkerFactory<in MediaGroupMessage<AudioMediaGroupPartContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, MediaGroupMessage<AudioMediaGroupPartContent>>
) = buildMediaGroupMessagesTrigger(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 <BC : BehaviourContext> BC.onDocumentsGroupMessages(
initialFilter: SimpleFilter<MediaGroupMessage<DocumentMediaGroupPartContent>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, MediaGroupMessage<DocumentMediaGroupPartContent>, Update>? = null,
markerFactory: MarkerFactory<in MediaGroupMessage<DocumentMediaGroupPartContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, MediaGroupMessage<DocumentMediaGroupPartContent>>
) = buildMediaGroupMessagesTrigger(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 <BC : BehaviourContext> BC.onVisualGalleryMessages(
initialFilter: SimpleFilter<MediaGroupMessage<VisualMediaGroupPartContent>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, MediaGroupMessage<VisualMediaGroupPartContent>, Update>? = null,
markerFactory: MarkerFactory<in MediaGroupMessage<VisualMediaGroupPartContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, MediaGroupMessage<VisualMediaGroupPartContent>>
) = buildMediaGroupMessagesTrigger(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 <BC : BehaviourContext> BC.onVisualMediaGroupMessages(
initialFilter: SimpleFilter<MediaGroupMessage<VisualMediaGroupPartContent>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, MediaGroupMessage<VisualMediaGroupPartContent>, Update>? = null,
markerFactory: MarkerFactory<in MediaGroupMessage<VisualMediaGroupPartContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, MediaGroupMessage<VisualMediaGroupPartContent>>
) = onVisualGalleryMessages(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 <BC : BehaviourContext> BC.onPhotoGalleryMessages(
initialFilter: SimpleFilter<MediaGroupMessage<PhotoContent>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, MediaGroupMessage<PhotoContent>, Update>? = null,
markerFactory: MarkerFactory<in MediaGroupMessage<PhotoContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, MediaGroupMessage<PhotoContent>>
) = buildMediaGroupMessagesTrigger(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 <BC : BehaviourContext> BC.onVideoGalleryMessages(
initialFilter: SimpleFilter<MediaGroupMessage<VideoContent>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, MediaGroupMessage<VideoContent>, Update>? = null,
markerFactory: MarkerFactory<in MediaGroupMessage<VideoContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, MediaGroupMessage<VideoContent>>
) = buildMediaGroupMessagesTrigger(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)

View File

@ -0,0 +1,164 @@
@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.utils.SimpleFilter
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.AnyMarkerFactory
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory
import dev.inmo.tgbotapi.extensions.utils.baseSentMessageUpdateOrNull
import dev.inmo.tgbotapi.extensions.utils.commonMessageOrNull
import dev.inmo.tgbotapi.extensions.utils.withContentOrNull
import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage
import dev.inmo.tgbotapi.types.message.content.*
import dev.inmo.tgbotapi.types.update.abstracts.Update
import dev.inmo.tgbotapi.utils.PreviewFeature
@PreviewFeature
internal suspend inline fun <BC : BehaviourContext, reified T : MediaGroupPartContent> BC.buildMediaGroupTrigger(
initialFilter: SimpleFilter<MediaGroupContent<T>>? = null,
noinline subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, MediaGroupContent<T>, Update>? = null,
markerFactory: MarkerFactory<in MediaGroupContent<T>, Any> = AnyMarkerFactory(),
noinline scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, MediaGroupContent<T>>
) = on(markerFactory, initialFilter, subcontextUpdatesFilter, scenarioReceiver) {
it.baseSentMessageUpdateOrNull() ?.data ?.commonMessageOrNull() ?.withContentOrNull<MediaGroupContent<*>>() ?.let {
if (it.content.group.all { it.content is T }) {
listOf(it.content as MediaGroupContent<T>)
} else {
null
}
} ?: emptyList()
}
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun <BC : BehaviourContext> BC.onMediaGroup(
initialFilter: SimpleFilter<MediaGroupContent<MediaGroupPartContent>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, MediaGroupContent<MediaGroupPartContent>, Update>? = null,
markerFactory: MarkerFactory<in MediaGroupContent<MediaGroupPartContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, MediaGroupContent<MediaGroupPartContent>>
) = 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 <BC : BehaviourContext> BC.onPlaylist(
initialFilter: SimpleFilter<MediaGroupContent<AudioMediaGroupPartContent>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, MediaGroupContent<AudioMediaGroupPartContent>, Update>? = null,
markerFactory: MarkerFactory<in MediaGroupContent<AudioMediaGroupPartContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, MediaGroupContent<AudioMediaGroupPartContent>>
) = 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 <BC : BehaviourContext> BC.onDocumentsGroup(
initialFilter: SimpleFilter<MediaGroupContent<DocumentMediaGroupPartContent>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, MediaGroupContent<DocumentMediaGroupPartContent>, Update>? = null,
markerFactory: MarkerFactory<in MediaGroupContent<DocumentMediaGroupPartContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, MediaGroupContent<DocumentMediaGroupPartContent>>
) = 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 <BC : BehaviourContext> BC.onVisualGallery(
initialFilter: SimpleFilter<MediaGroupContent<VisualMediaGroupPartContent>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, MediaGroupContent<VisualMediaGroupPartContent>, Update>? = null,
markerFactory: MarkerFactory<in MediaGroupContent<VisualMediaGroupPartContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, MediaGroupContent<VisualMediaGroupPartContent>>
) = 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 <BC : BehaviourContext> BC.onVisualMediaGroup(
initialFilter: SimpleFilter<MediaGroupContent<VisualMediaGroupPartContent>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, MediaGroupContent<VisualMediaGroupPartContent>, Update>? = null,
markerFactory: MarkerFactory<in MediaGroupContent<VisualMediaGroupPartContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, MediaGroupContent<VisualMediaGroupPartContent>>
) = 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 <BC : BehaviourContext> BC.onPhotoGallery(
initialFilter: SimpleFilter<MediaGroupContent<PhotoContent>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, MediaGroupContent<PhotoContent>, Update>? = null,
markerFactory: MarkerFactory<in MediaGroupContent<PhotoContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, MediaGroupContent<PhotoContent>>
) = 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 <BC : BehaviourContext> BC.onVideoGallery(
initialFilter: SimpleFilter<MediaGroupContent<VideoContent>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, MediaGroupContent<VideoContent>, Update>? = null,
markerFactory: MarkerFactory<in MediaGroupContent<VideoContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, MediaGroupContent<VideoContent>>
) = buildMediaGroupTrigger(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)

View File

@ -0,0 +1,5 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories
private val commonAnyMarker = MarkerFactory<Any, Any> { it }
fun <T> AnyMarkerFactory() = commonAnyMarker as MarkerFactory<T, T>

View File

@ -122,16 +122,16 @@ inline fun SendVisualMediaGroup(
allowSendingWithoutReply: Boolean? = null allowSendingWithoutReply: Boolean? = null
) = SendMediaGroup<VisualMediaGroupPartContent>(chatId, media, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply) ) = SendMediaGroup<VisualMediaGroupPartContent>(chatId, media, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply)
private object MessagesListSerializer: KSerializer<PossiblySentViaBotCommonMessage<MediaGroupContent>> { private object MessagesListSerializer: KSerializer<PossiblySentViaBotCommonMessage<MediaGroupContent<MediaGroupPartContent>>> {
private val serializer = ListSerializer(TelegramBotAPIMessageDeserializeOnlySerializerClass<PossiblySentViaBotCommonMessage<MediaGroupPartContent>>()) private val serializer = ListSerializer(TelegramBotAPIMessageDeserializeOnlySerializerClass<PossiblySentViaBotCommonMessage<MediaGroupPartContent>>())
override val descriptor: SerialDescriptor = serializer.descriptor override val descriptor: SerialDescriptor = serializer.descriptor
override fun deserialize(decoder: Decoder): PossiblySentViaBotCommonMessage<MediaGroupContent> { override fun deserialize(decoder: Decoder): PossiblySentViaBotCommonMessage<MediaGroupContent<MediaGroupPartContent>> {
val messages = serializer.deserialize(decoder) val messages = serializer.deserialize(decoder)
return messages.asMediaGroupMessage() return messages.asMediaGroupMessage()
} }
override fun serialize(encoder: Encoder, value: PossiblySentViaBotCommonMessage<MediaGroupContent>) { override fun serialize(encoder: Encoder, value: PossiblySentViaBotCommonMessage<MediaGroupContent<MediaGroupPartContent>>) {
serializer.serialize(encoder, value.content.group.map { it.sourceMessage }) serializer.serialize(encoder, value.content.group.map { it.sourceMessage })
} }
@ -152,8 +152,8 @@ data class SendMediaGroupData internal constructor(
override val replyToMessageId: MessageId? = null, override val replyToMessageId: MessageId? = null,
@SerialName(allowSendingWithoutReplyField) @SerialName(allowSendingWithoutReplyField)
override val allowSendingWithoutReply: Boolean? = null override val allowSendingWithoutReply: Boolean? = null
) : DataRequest<PossiblySentViaBotCommonMessage<MediaGroupContent>>, ) : DataRequest<PossiblySentViaBotCommonMessage<MediaGroupContent<MediaGroupPartContent>>>,
SendMessageRequest<PossiblySentViaBotCommonMessage<MediaGroupContent>> { SendMessageRequest<PossiblySentViaBotCommonMessage<MediaGroupContent<MediaGroupPartContent>>> {
@SerialName(mediaField) @SerialName(mediaField)
private val convertedMedia: String private val convertedMedia: String
get() = buildJsonArray { get() = buildJsonArray {
@ -166,7 +166,7 @@ data class SendMediaGroupData internal constructor(
override fun method(): String = "sendMediaGroup" override fun method(): String = "sendMediaGroup"
override val requestSerializer: SerializationStrategy<*> override val requestSerializer: SerializationStrategy<*>
get() = serializer() get() = serializer()
override val resultDeserializer: DeserializationStrategy<PossiblySentViaBotCommonMessage<MediaGroupContent>> override val resultDeserializer: DeserializationStrategy<PossiblySentViaBotCommonMessage<MediaGroupContent<MediaGroupPartContent>>>
get() = MessagesListSerializer get() = MessagesListSerializer
} }

View File

@ -24,14 +24,14 @@ sealed interface DocumentMediaGroupPartContent : MediaGroupPartContent {
sealed interface TextedMediaContent : MediaContent, TextedInput sealed interface TextedMediaContent : MediaContent, TextedInput
sealed interface MediaGroupCollectionContent : TextedMediaContent { sealed interface MediaGroupCollectionContent<T : MediaGroupPartContent> : TextedMediaContent {
@Serializable @Serializable
data class PartWrapper( data class PartWrapper<T : MediaGroupPartContent>(
val messageId: MessageId, val messageId: MessageId,
val content: MediaGroupPartContent, val content: T,
val sourceMessage: PossiblySentViaBotCommonMessage<MediaGroupPartContent> val sourceMessage: PossiblySentViaBotCommonMessage<T>
) )
val group: List<PartWrapper> val group: List<PartWrapper<T>>
val mediaGroupId: MediaGroupIdentifier val mediaGroupId: MediaGroupIdentifier
} }

View File

@ -14,10 +14,10 @@ import dev.inmo.tgbotapi.types.message.textsources.TextSource
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable
data class MediaGroupContent( data class MediaGroupContent<T : MediaGroupPartContent>(
override val group: List<MediaGroupCollectionContent.PartWrapper>, override val group: List<MediaGroupCollectionContent.PartWrapper<T>>,
override val mediaGroupId: MediaGroupIdentifier override val mediaGroupId: MediaGroupIdentifier
) : MediaGroupCollectionContent { ) : MediaGroupCollectionContent<T> {
val mainContent: MediaGroupPartContent val mainContent: MediaGroupPartContent
get() = group.first().content get() = group.first().content
override val media: TelegramMediaFile override val media: TelegramMediaFile

View File

@ -20,7 +20,7 @@ typealias VideoNoteMessage = CommonMessage<VideoNoteContent>
typealias StickerMessage = CommonMessage<StickerContent> typealias StickerMessage = CommonMessage<StickerContent>
typealias TextedMediaMessage = CommonMessage<TextedMediaContent> typealias TextedMediaMessage = CommonMessage<TextedMediaContent>
typealias VoiceMessage = CommonMessage<VoiceContent> typealias VoiceMessage = CommonMessage<VoiceContent>
typealias MediaGroupMessage = CommonMessage<MediaGroupContent> typealias MediaGroupMessage<T> = CommonMessage<MediaGroupContent<T>>
typealias AudioMediaGroupMessage = CommonMessage<AudioMediaGroupPartContent> typealias AudioMediaGroupMessage = CommonMessage<AudioMediaGroupPartContent>
typealias AudioMessage = CommonMessage<AudioContent> typealias AudioMessage = CommonMessage<AudioContent>
typealias DocumentMediaGroupMessage = CommonMessage<DocumentMediaGroupPartContent> typealias DocumentMediaGroupMessage = CommonMessage<DocumentMediaGroupPartContent>

View File

@ -27,7 +27,7 @@ import dev.inmo.tgbotapi.types.message.content.MediaGroupPartContent
import dev.inmo.tgbotapi.utils.RiskFeature import dev.inmo.tgbotapi.utils.RiskFeature
@RiskFeature("This API is experimental and can be changed without any notice, use with caution") @RiskFeature("This API is experimental and can be changed without any notice, use with caution")
fun List<PossiblySentViaBotCommonMessage<MediaGroupPartContent>>.asMediaGroupMessage(): PossiblySentViaBotCommonMessage<MediaGroupContent> { fun <T : MediaGroupPartContent> List<PossiblySentViaBotCommonMessage<T>>.asMediaGroupMessage(): PossiblySentViaBotCommonMessage<MediaGroupContent<T>> {
val sourceMessage = first() val sourceMessage = first()
val content = MediaGroupContent( val content = MediaGroupContent(
map { MediaGroupCollectionContent.PartWrapper(it.messageId, it.content, it) }, map { MediaGroupCollectionContent.PartWrapper(it.messageId, it.content, it) },

View File

@ -1194,16 +1194,16 @@ inline fun Message.requireGroupContentMessage(): GroupContentMessage<MessageCont
this as GroupContentMessage<MessageContent> this as GroupContentMessage<MessageContent>
@PreviewFeature @PreviewFeature
inline fun <T> Message.whenMediaGroupMessage(block: (MediaGroupMessage) -> T) = inline fun <T> Message.whenMediaGroupMessage(block: (MediaGroupMessage<MediaGroupPartContent>) -> T) =
asMediaGroupMessage()?.let(block) asMediaGroupMessage()?.let(block)
@PreviewFeature @PreviewFeature
inline fun Message.asMediaGroupMessage(): MediaGroupMessage? = inline fun Message.asMediaGroupMessage(): MediaGroupMessage<MediaGroupPartContent>? =
this as? MediaGroupMessage this as? MediaGroupMessage<MediaGroupPartContent>
@PreviewFeature @PreviewFeature
inline fun Message.requireMediaGroupMessage(): MediaGroupMessage = inline fun Message.requireMediaGroupMessage(): MediaGroupMessage<MediaGroupPartContent> =
this as MediaGroupMessage this as MediaGroupMessage<MediaGroupPartContent>
@PreviewFeature @PreviewFeature
inline fun <T> Message.whenPossiblyEditedMessage(block: (PossiblyEditedMessage) -> T) = inline fun <T> Message.whenPossiblyEditedMessage(block: (PossiblyEditedMessage) -> T) =

View File

@ -3509,16 +3509,16 @@ public inline fun <T> ResendableContent.ifTextedMediaContent(block: (TextedMedia
textedMediaContentOrNull() ?.let(block) textedMediaContentOrNull() ?.let(block)
public inline fun ResendableContent.mediaGroupCollectionContentOrNull(): public inline fun ResendableContent.mediaGroupCollectionContentOrNull():
MediaGroupCollectionContent? = this as? MediaGroupCollectionContent<MediaGroupPartContent>? = this as?
dev.inmo.tgbotapi.types.message.content.MediaGroupCollectionContent dev.inmo.tgbotapi.types.message.content.MediaGroupCollectionContent<dev.inmo.tgbotapi.types.message.content.MediaGroupPartContent>
public inline fun ResendableContent.mediaGroupCollectionContentOrThrow(): public inline fun ResendableContent.mediaGroupCollectionContentOrThrow():
MediaGroupCollectionContent = this as MediaGroupCollectionContent<MediaGroupPartContent> = this as
dev.inmo.tgbotapi.types.message.content.MediaGroupCollectionContent dev.inmo.tgbotapi.types.message.content.MediaGroupCollectionContent<dev.inmo.tgbotapi.types.message.content.MediaGroupPartContent>
public inline fun <T> public inline fun <T>
ResendableContent.ifMediaGroupCollectionContent(block: (MediaGroupCollectionContent) -> T): T? = ResendableContent.ifMediaGroupCollectionContent(block: (MediaGroupCollectionContent<MediaGroupPartContent>) -> T):
mediaGroupCollectionContentOrNull() ?.let(block) T? = mediaGroupCollectionContentOrNull() ?.let(block)
public inline fun ResendableContent.mediaGroupPartContentOrNull(): MediaGroupPartContent? = this as? public inline fun ResendableContent.mediaGroupPartContentOrNull(): MediaGroupPartContent? = this as?
dev.inmo.tgbotapi.types.message.content.MediaGroupPartContent dev.inmo.tgbotapi.types.message.content.MediaGroupPartContent
@ -3633,14 +3633,17 @@ public inline fun <T>
ResendableContent.ifStaticLocationContent(block: (StaticLocationContent) -> T): T? = ResendableContent.ifStaticLocationContent(block: (StaticLocationContent) -> T): T? =
staticLocationContentOrNull() ?.let(block) staticLocationContentOrNull() ?.let(block)
public inline fun ResendableContent.mediaGroupContentOrNull(): MediaGroupContent? = this as? public inline fun ResendableContent.mediaGroupContentOrNull():
dev.inmo.tgbotapi.types.message.content.MediaGroupContent MediaGroupContent<MediaGroupPartContent>? = this as?
dev.inmo.tgbotapi.types.message.content.MediaGroupContent<dev.inmo.tgbotapi.types.message.content.MediaGroupPartContent>
public inline fun ResendableContent.mediaGroupContentOrThrow(): MediaGroupContent = this as public inline fun ResendableContent.mediaGroupContentOrThrow():
dev.inmo.tgbotapi.types.message.content.MediaGroupContent MediaGroupContent<MediaGroupPartContent> = this as
dev.inmo.tgbotapi.types.message.content.MediaGroupContent<dev.inmo.tgbotapi.types.message.content.MediaGroupPartContent>
public inline fun <T> ResendableContent.ifMediaGroupContent(block: (MediaGroupContent) -> T): T? = public inline fun <T>
mediaGroupContentOrNull() ?.let(block) ResendableContent.ifMediaGroupContent(block: (MediaGroupContent<MediaGroupPartContent>) -> T):
T? = mediaGroupContentOrNull() ?.let(block)
public inline fun ResendableContent.photoContentOrNull(): PhotoContent? = this as? public inline fun ResendableContent.photoContentOrNull(): PhotoContent? = this as?
dev.inmo.tgbotapi.types.message.content.PhotoContent dev.inmo.tgbotapi.types.message.content.PhotoContent

View File

@ -60,7 +60,7 @@ fun TelegramBot.longPollingFlow(
*/ */
if ( if (
originalUpdates.size == getUpdatesLimit.last originalUpdates.size == getUpdatesLimit.last
&& ((converted.last() as? BaseSentMessageUpdate) ?.data as? CommonMessage<*>) ?.content is MediaGroupContent && ((converted.last() as? BaseSentMessageUpdate) ?.data as? CommonMessage<*>) ?.content is MediaGroupContent<*>
) { ) {
converted - converted.last() converted - converted.last()
} else { } else {