1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2024-11-22 16:23:48 +00:00

Merge pull request #97 from InsanusMokrassar/0.27.11

0.27.11
This commit is contained in:
InsanusMokrassar 2020-08-14 18:43:51 +06:00 committed by GitHub
commit 5d1c59ff75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 178 additions and 8 deletions

View File

@ -49,6 +49,43 @@
* `closePollExactAfter` * `closePollExactAfter`
* `closePollAfter` * `closePollAfter`
### 0.27.11
* `TelegramBotAPI-extensions-utils`:
* `Flow<Iterable<T>>.flatMap` extension was added
* Extensions for `FlowUpdatesFilter` were added:
* `FlowsUpdatesFilter#allSentMessagesFlow` (combination of `messageFlow` and `channelPostFlow`)
* `FlowsUpdatesFilter#allSentMediaGroupsFlow` (combination of `messageMediaGroupFlow` and `channelPostMediaGroupFlow`)
* `FlowsUpdatesFilter#sentMessages`
* `FlowsUpdatesFilter#sentMessagesWithMediaGroups`
* `FlowsUpdatesFilter#photoMessagesWithMediaGroups`
* `FlowsUpdatesFilter#imageMessagesWithMediaGroups`
* `FlowsUpdatesFilter#videoMessagesWithMediaGroups`
* `FlowsUpdatesFilter#mediaGroupMessages`
* `FlowsUpdatesFilter#mediaGroupPhotosMessages`
* `FlowsUpdatesFilter#mediaGroupVideosMessages`
* A lot of extensions like `Flow<BaseSentMessageUpdate>#textMessages` were added:
* `Flow<BaseSentMessageUpdate>#animationMessages`
* `Flow<BaseSentMessageUpdate>#audioMessages`
* `Flow<BaseSentMessageUpdate>#contactMessages`
* `Flow<BaseSentMessageUpdate>#diceMessages`
* `Flow<BaseSentMessageUpdate>#documentMessages`
* `Flow<BaseSentMessageUpdate>#gameMessages`
* `Flow<BaseSentMessageUpdate>#invoiceMessages`
* `Flow<BaseSentMessageUpdate>#locationMessages`
* `Flow<BaseSentMessageUpdate>#photoMessages`
* `Flow<BaseSentMessageUpdate>#imageMessages`
* `Flow<BaseSentMessageUpdate>#pollMessages`
* `Flow<BaseSentMessageUpdate>#stickerMessages`
* `Flow<BaseSentMessageUpdate>#textMessages`
* `Flow<BaseSentMessageUpdate>#venueMessages`
* `Flow<BaseSentMessageUpdate>#videoMessages`
* `Flow<BaseSentMessageUpdate>#videoNoteMessages`
* `Flow<BaseSentMessageUpdate>#voiceMessages`
* `Flow<BaseSentMessageUpdate>#mediaGroupMessages`
* `Flow<BaseSentMessageUpdate>#mediaGroupPhotosMessages`
* `Flow<BaseSentMessageUpdate>#mediaGroupVideosMessages`
### 0.27.10 ### 0.27.10
* `TelegramBotAPI-extensions-api`: * `TelegramBotAPI-extensions-api`:

View File

@ -5,6 +5,9 @@ import kotlinx.coroutines.channels.BroadcastChannel
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
/**
* Analog of [merge] function for [Flow]s. The difference is in the usage of [BroadcastChannel] in this case
*/
fun <T> aggregateFlows( fun <T> aggregateFlows(
withScope: CoroutineScope, withScope: CoroutineScope,
vararg flows: Flow<T>, vararg flows: Flow<T>,
@ -18,3 +21,19 @@ fun <T> aggregateFlows(
} }
return bc.asFlow() return bc.asFlow()
} }
fun <T> Flow<Iterable<T>>.flatMap(): Flow<T> = flow {
collect {
it.forEach {
emit(it)
}
}
}
fun <T, R> Flow<T>.flatMap(mapper: (T) -> Iterable<R>): Flow<R> = flow {
collect {
mapper(it).forEach {
emit(it)
}
}
}

View File

@ -0,0 +1,19 @@
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.extensions
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.flow.Flow
import kotlinx.coroutines.flow.merge
val FlowsUpdatesFilter.allSentMessagesFlow: Flow<BaseSentMessageUpdate>
get() = merge(
messageFlow,
channelPostFlow
)
val FlowsUpdatesFilter.allSentMediaGroupsFlow: Flow<SentMediaGroupUpdate>
get() = merge(
messageMediaGroupFlow,
channelPostMediaGroupFlow
)

View File

@ -1,12 +1,17 @@
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.shortcuts package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.shortcuts
import com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.aggregateFlows 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.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.abstracts.ContentMessage
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.* 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.abstracts.MessageContent
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.* import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.*
import com.github.insanusmokrassar.TelegramBotAPI.types.message.payments.InvoiceContent 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 com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.FlowsUpdatesFilter
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
@ -19,60 +24,120 @@ inline fun <reified T : MessageContent> filterForContentMessage(): suspend (Cont
} }
} }
@Suppress("UNCHECKED_CAST")
inline fun <reified T: MessageContent> Flow<BaseSentMessageUpdate>.filterContentMessages(
): Flow<ContentMessage<T>> = asContentMessagesFlow().mapNotNull(filterForContentMessage())
inline fun <reified T : MediaGroupContent> Flow<SentMediaGroupUpdate>.filterMediaGroupMessages(
): Flow<List<CommonMessage<T>>> = map {
it.data.mapNotNull { message ->
if (message.content is T) {
message as CommonMessage<T>
} else {
null
}
}
}
/** /**
* @param scopeToIncludeChannels This parameter is required when you want to include [textMessages] for channels too. * @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 agregate messages from [FlowsUpdatesFilter.messageFlow] and * 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 * [FlowsUpdatesFilter.channelPostFlow]. In case it is null will be used [Flow]s mapping
*/ */
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
inline fun <reified T: MessageContent> FlowsUpdatesFilter.filterContentMessages( inline fun <reified T: MessageContent> FlowsUpdatesFilter.filterContentMessages(
scopeToIncludeChannels: CoroutineScope? = null scopeToIncludeChannels: CoroutineScope? = null
): Flow<ContentMessage<T>> { ): Flow<ContentMessage<T>> {
val filter = filterForContentMessage<T>() return (scopeToIncludeChannels ?.let { scope ->
return scopeToIncludeChannels ?.let { scope ->
aggregateFlows( aggregateFlows(
scope, scope,
messageFlow.asContentMessagesFlow().mapNotNull(filter), messageFlow,
channelPostFlow.asContentMessagesFlow().mapNotNull(filter) channelPostFlow
) )
} ?: messageFlow.asContentMessagesFlow().mapNotNull(filter) } ?: 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 <reified T: MediaGroupContent> FlowsUpdatesFilter.filterMediaGroupMessages(
scopeToIncludeChannels: CoroutineScope? = null
): Flow<List<CommonMessage<T>>> {
return (scopeToIncludeChannels ?.let { scope ->
aggregateFlows(
scope,
messageMediaGroupFlow,
channelPostMediaGroupFlow
)
} ?: messageMediaGroupFlow).filterMediaGroupMessages()
}
fun FlowsUpdatesFilter.sentMessages(
scopeToIncludeChannels: CoroutineScope? = null
): Flow<ContentMessage<MessageContent>> = filterContentMessages(scopeToIncludeChannels)
fun FlowsUpdatesFilter.sentMessagesWithMediaGroups(
scopeToIncludeChannels: CoroutineScope? = null
): Flow<ContentMessage<MessageContent>> = merge(
sentMessages(scopeToIncludeChannels),
mediaGroupMessages(scopeToIncludeChannels).flatMap {
it.mapNotNull { it as? ContentMessage<MessageContent> }
}
)
fun Flow<BaseSentMessageUpdate>.animationMessages() = filterContentMessages<AnimationContent>()
fun FlowsUpdatesFilter.animationMessages( fun FlowsUpdatesFilter.animationMessages(
scopeToIncludeChannels: CoroutineScope? = null scopeToIncludeChannels: CoroutineScope? = null
) = filterContentMessages<AnimationContent>(scopeToIncludeChannels) ) = filterContentMessages<AnimationContent>(scopeToIncludeChannels)
fun Flow<BaseSentMessageUpdate>.audioMessages() = filterContentMessages<AudioContent>()
fun FlowsUpdatesFilter.audioMessages( fun FlowsUpdatesFilter.audioMessages(
scopeToIncludeChannels: CoroutineScope? = null scopeToIncludeChannels: CoroutineScope? = null
) = filterContentMessages<AudioContent>(scopeToIncludeChannels) ) = filterContentMessages<AudioContent>(scopeToIncludeChannels)
fun Flow<BaseSentMessageUpdate>.contactMessages() = filterContentMessages<ContactContent>()
fun FlowsUpdatesFilter.contactMessages( fun FlowsUpdatesFilter.contactMessages(
scopeToIncludeChannels: CoroutineScope? = null scopeToIncludeChannels: CoroutineScope? = null
) = filterContentMessages<ContactContent>(scopeToIncludeChannels) ) = filterContentMessages<ContactContent>(scopeToIncludeChannels)
fun Flow<BaseSentMessageUpdate>.diceMessages() = filterContentMessages<DiceContent>()
fun FlowsUpdatesFilter.diceMessages( fun FlowsUpdatesFilter.diceMessages(
scopeToIncludeChannels: CoroutineScope? = null scopeToIncludeChannels: CoroutineScope? = null
) = filterContentMessages<DiceContent>(scopeToIncludeChannels) ) = filterContentMessages<DiceContent>(scopeToIncludeChannels)
fun Flow<BaseSentMessageUpdate>.documentMessages() = filterContentMessages<DocumentContent>()
fun FlowsUpdatesFilter.documentMessages( fun FlowsUpdatesFilter.documentMessages(
scopeToIncludeChannels: CoroutineScope? = null scopeToIncludeChannels: CoroutineScope? = null
) = filterContentMessages<DocumentContent>(scopeToIncludeChannels) ) = filterContentMessages<DocumentContent>(scopeToIncludeChannels)
fun Flow<BaseSentMessageUpdate>.gameMessages() = filterContentMessages<GameContent>()
fun FlowsUpdatesFilter.gameMessages( fun FlowsUpdatesFilter.gameMessages(
scopeToIncludeChannels: CoroutineScope? = null scopeToIncludeChannels: CoroutineScope? = null
) = filterContentMessages<GameContent>(scopeToIncludeChannels) ) = filterContentMessages<GameContent>(scopeToIncludeChannels)
fun Flow<BaseSentMessageUpdate>.invoiceMessages() = filterContentMessages<InvoiceContent>()
fun FlowsUpdatesFilter.invoiceMessages( fun FlowsUpdatesFilter.invoiceMessages(
scopeToIncludeChannels: CoroutineScope? = null scopeToIncludeChannels: CoroutineScope? = null
) = filterContentMessages<InvoiceContent>(scopeToIncludeChannels) ) = filterContentMessages<InvoiceContent>(scopeToIncludeChannels)
fun Flow<BaseSentMessageUpdate>.locationMessages() = filterContentMessages<LocationContent>()
fun FlowsUpdatesFilter.locationMessages( fun FlowsUpdatesFilter.locationMessages(
scopeToIncludeChannels: CoroutineScope? = null scopeToIncludeChannels: CoroutineScope? = null
) = filterContentMessages<LocationContent>(scopeToIncludeChannels) ) = filterContentMessages<LocationContent>(scopeToIncludeChannels)
fun Flow<BaseSentMessageUpdate>.photoMessages() = filterContentMessages<PhotoContent>()
fun Flow<BaseSentMessageUpdate>.imageMessages() = photoMessages()
fun FlowsUpdatesFilter.photoMessages( fun FlowsUpdatesFilter.photoMessages(
scopeToIncludeChannels: CoroutineScope? = null scopeToIncludeChannels: CoroutineScope? = null
) = filterContentMessages<PhotoContent>(scopeToIncludeChannels) ) = filterContentMessages<PhotoContent>(scopeToIncludeChannels)
fun FlowsUpdatesFilter.photoMessagesWithMediaGroups(
scopeToIncludeChannels: CoroutineScope? = null
) = merge(
filterContentMessages<PhotoContent>(scopeToIncludeChannels),
mediaGroupPhotosMessages(scopeToIncludeChannels).flatMap()
)
/** /**
* Shortcut for [photoMessages] * Shortcut for [photoMessages]
*/ */
@ -80,33 +145,63 @@ fun FlowsUpdatesFilter.photoMessages(
inline fun FlowsUpdatesFilter.imageMessages( inline fun FlowsUpdatesFilter.imageMessages(
scopeToIncludeChannels: CoroutineScope? = null scopeToIncludeChannels: CoroutineScope? = null
) = photoMessages(scopeToIncludeChannels) ) = photoMessages(scopeToIncludeChannels)
fun FlowsUpdatesFilter.imageMessagesWithMediaGroups(
scopeToIncludeChannels: CoroutineScope? = null
) = photoMessagesWithMediaGroups(scopeToIncludeChannels)
fun Flow<BaseSentMessageUpdate>.pollMessages() = filterContentMessages<PollContent>()
fun FlowsUpdatesFilter.pollMessages( fun FlowsUpdatesFilter.pollMessages(
scopeToIncludeChannels: CoroutineScope? = null scopeToIncludeChannels: CoroutineScope? = null
) = filterContentMessages<PollContent>(scopeToIncludeChannels) ) = filterContentMessages<PollContent>(scopeToIncludeChannels)
fun Flow<BaseSentMessageUpdate>.stickerMessages() = filterContentMessages<StickerContent>()
fun FlowsUpdatesFilter.stickerMessages( fun FlowsUpdatesFilter.stickerMessages(
scopeToIncludeChannels: CoroutineScope? = null scopeToIncludeChannels: CoroutineScope? = null
) = filterContentMessages<StickerContent>(scopeToIncludeChannels) ) = filterContentMessages<StickerContent>(scopeToIncludeChannels)
fun Flow<BaseSentMessageUpdate>.textMessages() = filterContentMessages<TextContent>()
fun FlowsUpdatesFilter.textMessages( fun FlowsUpdatesFilter.textMessages(
scopeToIncludeChannels: CoroutineScope? = null scopeToIncludeChannels: CoroutineScope? = null
) = filterContentMessages<TextContent>(scopeToIncludeChannels) ) = filterContentMessages<TextContent>(scopeToIncludeChannels)
fun Flow<BaseSentMessageUpdate>.venueMessages() = filterContentMessages<VenueContent>()
fun FlowsUpdatesFilter.venueMessages( fun FlowsUpdatesFilter.venueMessages(
scopeToIncludeChannels: CoroutineScope? = null scopeToIncludeChannels: CoroutineScope? = null
) = filterContentMessages<VenueContent>(scopeToIncludeChannels) ) = filterContentMessages<VenueContent>(scopeToIncludeChannels)
fun Flow<BaseSentMessageUpdate>.videoMessages() = filterContentMessages<VideoContent>()
fun FlowsUpdatesFilter.videoMessages( fun FlowsUpdatesFilter.videoMessages(
scopeToIncludeChannels: CoroutineScope? = null scopeToIncludeChannels: CoroutineScope? = null
) = filterContentMessages<VideoContent>(scopeToIncludeChannels) ) = filterContentMessages<VideoContent>(scopeToIncludeChannels)
fun FlowsUpdatesFilter.videoMessagesWithMediaGroups(
scopeToIncludeChannels: CoroutineScope? = null
) = merge(
filterContentMessages<VideoContent>(scopeToIncludeChannels),
mediaGroupVideosMessages(scopeToIncludeChannels).flatMap()
)
fun Flow<BaseSentMessageUpdate>.videoNoteMessages() = filterContentMessages<VideoNoteContent>()
fun FlowsUpdatesFilter.videoNoteMessages( fun FlowsUpdatesFilter.videoNoteMessages(
scopeToIncludeChannels: CoroutineScope? = null scopeToIncludeChannels: CoroutineScope? = null
) = filterContentMessages<VideoNoteContent>(scopeToIncludeChannels) ) = filterContentMessages<VideoNoteContent>(scopeToIncludeChannels)
fun Flow<BaseSentMessageUpdate>.voiceMessages() = filterContentMessages<VoiceContent>()
fun FlowsUpdatesFilter.voiceMessages( fun FlowsUpdatesFilter.voiceMessages(
scopeToIncludeChannels: CoroutineScope? = null scopeToIncludeChannels: CoroutineScope? = null
) = filterContentMessages<VoiceContent>(scopeToIncludeChannels) ) = filterContentMessages<VoiceContent>(scopeToIncludeChannels)
fun Flow<SentMediaGroupUpdate>.mediaGroupMessages() = filterMediaGroupMessages<MediaGroupContent>()
fun FlowsUpdatesFilter.mediaGroupMessages(
scopeToIncludeChannels: CoroutineScope? = null
) = filterMediaGroupMessages<MediaGroupContent>(scopeToIncludeChannels)
fun Flow<SentMediaGroupUpdate>.mediaGroupPhotosMessages() = filterMediaGroupMessages<PhotoContent>()
fun FlowsUpdatesFilter.mediaGroupPhotosMessages(
scopeToIncludeChannels: CoroutineScope? = null
) = filterMediaGroupMessages<PhotoContent>(scopeToIncludeChannels)
fun Flow<SentMediaGroupUpdate>.mediaGroupVideosMessages() = filterMediaGroupMessages<VideoContent>()
fun FlowsUpdatesFilter.mediaGroupVideosMessages(
scopeToIncludeChannels: CoroutineScope? = null
) = filterMediaGroupMessages<VideoContent>(scopeToIncludeChannels)

View File

@ -114,7 +114,7 @@ fun RequestsExecutor.startGettingOfUpdatesByLongPolling(
pollAnswerCallback: UpdateReceiver<PollAnswerUpdate>? = null, pollAnswerCallback: UpdateReceiver<PollAnswerUpdate>? = null,
timeoutSeconds: Seconds = 30, timeoutSeconds: Seconds = 30,
exceptionsHandler: ExceptionHandler<Unit>? = null, exceptionsHandler: ExceptionHandler<Unit>? = null,
scope: CoroutineScope = GlobalScope scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
): Job { ): Job {
return startGettingOfUpdatesByLongPolling( return startGettingOfUpdatesByLongPolling(
SimpleUpdatesFilter( SimpleUpdatesFilter(

View File

@ -9,6 +9,6 @@ ktor_version=1.3.2
javax_activation_version=1.1.1 javax_activation_version=1.1.1
library_group=com.github.insanusmokrassar library_group=com.github.insanusmokrassar
library_version=0.27.10 library_version=0.27.11
gradle_bintray_plugin_version=1.8.4 gradle_bintray_plugin_version=1.8.4