package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.shortcuts import com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.aggregateFlows import com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.flatMap import com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.updates.asContentMessagesFlow import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.CommonMessage import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.* import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MediaGroupContent import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MessageContent import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.* import com.github.insanusmokrassar.TelegramBotAPI.types.message.payments.InvoiceContent import com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates.SentMediaGroupUpdate import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.BaseSentMessageUpdate import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.FlowsUpdatesFilter import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.* inline fun filterForContentMessage(): suspend (ContentMessage<*>) -> ContentMessage? = { if (it.content is T) { it as ContentMessage } else { null } } @Suppress("UNCHECKED_CAST") inline fun Flow.filterContentMessages( ): Flow> = asContentMessagesFlow().mapNotNull(filterForContentMessage()) inline fun Flow.filterMediaGroupMessages( ): Flow>> = map { it.data.mapNotNull { message -> if (message.content is T) { message as CommonMessage } else { null } } } /** * @param scopeToIncludeChannels This parameter is required when you want to include [textMessages] for channels too. * In this case will be created new channel which will aggregate messages from [FlowsUpdatesFilter.messageFlow] and * [FlowsUpdatesFilter.channelPostFlow]. In case it is null will be used [Flow]s mapping */ @Suppress("UNCHECKED_CAST") inline fun FlowsUpdatesFilter.filterContentMessages( scopeToIncludeChannels: CoroutineScope? = null ): Flow> { return (scopeToIncludeChannels ?.let { scope -> aggregateFlows( scope, messageFlow, channelPostFlow ) } ?: messageFlow).filterContentMessages() } /** * @param scopeToIncludeChannels This parameter is required when you want to include [SentMediaGroupUpdate] for channels * too. In this case will be created new channel which will aggregate messages from [FlowsUpdatesFilter.messageFlow] and * [FlowsUpdatesFilter.channelPostFlow]. In case it is null will be used [Flow]s mapping */ @Suppress("UNCHECKED_CAST") inline fun FlowsUpdatesFilter.filterMediaGroupMessages( scopeToIncludeChannels: CoroutineScope? = null ): Flow>> { return (scopeToIncludeChannels ?.let { scope -> aggregateFlows( scope, messageMediaGroupFlow, channelPostMediaGroupFlow ) } ?: messageMediaGroupFlow).filterMediaGroupMessages() } fun FlowsUpdatesFilter.sentMessages( scopeToIncludeChannels: CoroutineScope? = null ): Flow> = filterContentMessages(scopeToIncludeChannels) fun FlowsUpdatesFilter.sentMessagesWithMediaGroups( scopeToIncludeChannels: CoroutineScope? = null ): Flow> = merge( sentMessages(scopeToIncludeChannels), mediaGroupMessages(scopeToIncludeChannels).flatMap { it.mapNotNull { it as? ContentMessage } } ) fun Flow.animationMessages() = filterContentMessages() fun FlowsUpdatesFilter.animationMessages( scopeToIncludeChannels: CoroutineScope? = null ) = filterContentMessages(scopeToIncludeChannels) fun Flow.audioMessages() = filterContentMessages() fun FlowsUpdatesFilter.audioMessages( scopeToIncludeChannels: CoroutineScope? = null ) = filterContentMessages(scopeToIncludeChannels) fun Flow.contactMessages() = filterContentMessages() fun FlowsUpdatesFilter.contactMessages( scopeToIncludeChannels: CoroutineScope? = null ) = filterContentMessages(scopeToIncludeChannels) fun Flow.diceMessages() = filterContentMessages() fun FlowsUpdatesFilter.diceMessages( scopeToIncludeChannels: CoroutineScope? = null ) = filterContentMessages(scopeToIncludeChannels) fun Flow.documentMessages() = filterContentMessages() fun FlowsUpdatesFilter.documentMessages( scopeToIncludeChannels: CoroutineScope? = null ) = filterContentMessages(scopeToIncludeChannels) fun Flow.gameMessages() = filterContentMessages() fun FlowsUpdatesFilter.gameMessages( scopeToIncludeChannels: CoroutineScope? = null ) = filterContentMessages(scopeToIncludeChannels) fun Flow.invoiceMessages() = filterContentMessages() fun FlowsUpdatesFilter.invoiceMessages( scopeToIncludeChannels: CoroutineScope? = null ) = filterContentMessages(scopeToIncludeChannels) fun Flow.locationMessages() = filterContentMessages() fun FlowsUpdatesFilter.locationMessages( scopeToIncludeChannels: CoroutineScope? = null ) = filterContentMessages(scopeToIncludeChannels) fun Flow.photoMessages() = filterContentMessages() fun Flow.imageMessages() = photoMessages() fun FlowsUpdatesFilter.photoMessages( scopeToIncludeChannels: CoroutineScope? = null ) = filterContentMessages(scopeToIncludeChannels) fun FlowsUpdatesFilter.photoMessagesWithMediaGroups( scopeToIncludeChannels: CoroutineScope? = null ) = merge( filterContentMessages(scopeToIncludeChannels), mediaGroupPhotosMessages(scopeToIncludeChannels).flatMap() ) /** * Shortcut for [photoMessages] */ @Suppress("NOTHING_TO_INLINE") inline fun FlowsUpdatesFilter.imageMessages( scopeToIncludeChannels: CoroutineScope? = null ) = photoMessages(scopeToIncludeChannels) fun FlowsUpdatesFilter.imageMessagesWithMediaGroups( scopeToIncludeChannels: CoroutineScope? = null ) = photoMessagesWithMediaGroups(scopeToIncludeChannels) fun Flow.pollMessages() = filterContentMessages() fun FlowsUpdatesFilter.pollMessages( scopeToIncludeChannels: CoroutineScope? = null ) = filterContentMessages(scopeToIncludeChannels) fun Flow.stickerMessages() = filterContentMessages() fun FlowsUpdatesFilter.stickerMessages( scopeToIncludeChannels: CoroutineScope? = null ) = filterContentMessages(scopeToIncludeChannels) fun Flow.textMessages() = filterContentMessages() fun FlowsUpdatesFilter.textMessages( scopeToIncludeChannels: CoroutineScope? = null ) = filterContentMessages(scopeToIncludeChannels) fun Flow.venueMessages() = filterContentMessages() fun FlowsUpdatesFilter.venueMessages( scopeToIncludeChannels: CoroutineScope? = null ) = filterContentMessages(scopeToIncludeChannels) fun Flow.videoMessages() = filterContentMessages() fun FlowsUpdatesFilter.videoMessages( scopeToIncludeChannels: CoroutineScope? = null ) = filterContentMessages(scopeToIncludeChannels) fun FlowsUpdatesFilter.videoMessagesWithMediaGroups( scopeToIncludeChannels: CoroutineScope? = null ) = merge( filterContentMessages(scopeToIncludeChannels), mediaGroupVideosMessages(scopeToIncludeChannels).flatMap() ) fun Flow.videoNoteMessages() = filterContentMessages() fun FlowsUpdatesFilter.videoNoteMessages( scopeToIncludeChannels: CoroutineScope? = null ) = filterContentMessages(scopeToIncludeChannels) fun Flow.voiceMessages() = filterContentMessages() fun FlowsUpdatesFilter.voiceMessages( scopeToIncludeChannels: CoroutineScope? = null ) = filterContentMessages(scopeToIncludeChannels) fun Flow.mediaGroupMessages() = filterMediaGroupMessages() fun FlowsUpdatesFilter.mediaGroupMessages( scopeToIncludeChannels: CoroutineScope? = null ) = filterMediaGroupMessages(scopeToIncludeChannels) fun Flow.mediaGroupPhotosMessages() = filterMediaGroupMessages() fun FlowsUpdatesFilter.mediaGroupPhotosMessages( scopeToIncludeChannels: CoroutineScope? = null ) = filterMediaGroupMessages(scopeToIncludeChannels) fun Flow.mediaGroupVideosMessages() = filterMediaGroupMessages() fun FlowsUpdatesFilter.mediaGroupVideosMessages( scopeToIncludeChannels: CoroutineScope? = null ) = filterMediaGroupMessages(scopeToIncludeChannels)