1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2025-11-16 20:10:18 +00:00

Compare commits

..

12 Commits

16 changed files with 855 additions and 97 deletions

View File

@@ -1,5 +1,24 @@
# TelegramBotAPI changelog
## 7.1.3
* `Versions`:
* `Serialization`: `1.5.0` -> `1.5.1`
* `MicroUtils`: `0.18.1` -> `0.18.4`
* `Core`:
* Actualize kdocs in `InputFile`
* `BehaviourBuilder`:
* Now it is possible to use `waitMediaContent`/`waitMediaContentMessage`/`onMediaContent`
* Add `onMention`/`waitMention` functionality
* Add opportunity to map content with extensions to `Flow`
## 7.1.2
* `Versions`:
* `MicroUtils`: `0.18.0` -> `0.18.1`
* `Core`:
* Now it is possible to serialize `Sticker`s
## 7.1.1
* `Versions`:

View File

@@ -6,4 +6,4 @@ kotlin.incremental=true
kotlin.incremental.js=true
library_group=dev.inmo
library_version=7.1.1
library_version=7.1.3

View File

@@ -1,7 +1,7 @@
[versions]
kotlin = "1.8.21"
kotlin-serialization = "1.5.0"
kotlin-serialization = "1.5.1"
kotlin-coroutines = "1.6.4"
javax-activation = "1.1.1"
@@ -11,9 +11,9 @@ uuid = "0.7.0"
ktor = "2.3.0"
ksp = "1.8.21-1.0.11"
kotlin-poet = "1.13.1"
kotlin-poet = "1.13.2"
microutils = "0.18.0"
microutils = "0.18.4"
github-release-plugin = "2.4.1"
dokka = "1.8.10"

View File

@@ -10,117 +10,127 @@ import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.lowLevelRiskFeatureMessage
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapNotNull
typealias CommonMessageToContentMapper<T> = suspend CommonMessage<T>.() -> T?
@RiskFeature(lowLevelRiskFeatureMessage)
suspend inline fun <reified O : MessageContent> BehaviourContext.waitContent(
suspend inline fun BehaviourContext.waitContent(
initRequest: Request<*>? = null,
noinline errorFactory: NullableRequestBuilder<*> = { null }
): Flow<O> = waitContentMessage<O>(initRequest, errorFactory).map { it.content }
): Flow<MessageContent> = waitContentMessage(initRequest, errorFactory).map { it.content }
inline fun <reified T : MessageContent> Flow<MessageContent>.mapContent() = mapNotNull { it as? T }
suspend fun BehaviourContext.waitAnyContent(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<MessageContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory)
suspend fun BehaviourContext.waitTextedContent(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent(initRequest, errorFactory).mapContent<TextedContent>()
suspend fun BehaviourContext.waitContact(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<ContactContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<ContactContent>()
suspend fun BehaviourContext.waitDice(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<DiceContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<DiceContent>()
suspend fun BehaviourContext.waitGame(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<GameContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<GameContent>()
suspend fun BehaviourContext.waitLocation(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<LocationContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<LocationContent>()
suspend fun BehaviourContext.waitLiveLocation(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<LiveLocationContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<LiveLocationContent>()
suspend fun BehaviourContext.waitStaticLocation(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<StaticLocationContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<StaticLocationContent>()
suspend fun BehaviourContext.waitPoll(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<PollContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<PollContent>()
suspend fun BehaviourContext.waitText(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<TextContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<TextContent>()
suspend fun BehaviourContext.waitVenue(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<VenueContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<VenueContent>()
suspend fun BehaviourContext.waitAudioMediaGroupContent(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null },
) = waitContent<AudioMediaGroupPartContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<AudioMediaGroupPartContent>()
suspend fun BehaviourContext.waitDocumentMediaGroupContent(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<DocumentMediaGroupPartContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<DocumentMediaGroupPartContent>()
suspend fun BehaviourContext.waitMedia(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<MediaContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<MediaContent>()
suspend fun BehaviourContext.waitAnyMediaGroupContent(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null },
) = waitContent<MediaGroupPartContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<MediaGroupPartContent>()
suspend fun BehaviourContext.waitVisualMediaGroupContent(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null },
) = waitContent<VisualMediaGroupPartContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<VisualMediaGroupPartContent>()
suspend fun BehaviourContext.waitTextedMediaContent(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null },
) = waitContent<TextedMediaContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<TextedMediaContent>()
suspend fun BehaviourContext.waitAnimation(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<AnimationContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<AnimationContent>()
suspend fun BehaviourContext.waitAudio(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null },
) = waitContent<AudioContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<AudioContent>()
suspend fun BehaviourContext.waitDocument(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null },
) = waitContent<DocumentContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<DocumentContent>()
suspend fun BehaviourContext.waitPhoto(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null },
) = waitContent<PhotoContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<PhotoContent>()
suspend fun BehaviourContext.waitSticker(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<StickerContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<StickerContent>()
suspend fun BehaviourContext.waitVideo(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<VideoContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<VideoContent>()
suspend fun BehaviourContext.waitVideoNote(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<VideoNoteContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<VideoNoteContent>()
suspend fun BehaviourContext.waitVoice(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<VoiceContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<VoiceContent>()
suspend fun BehaviourContext.waitInvoice(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<InvoiceContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<InvoiceContent>()
suspend fun BehaviourContext.waitVisualContent(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<VisualMediaGroupPartContent>(initRequest, errorFactory)
) = waitContent(initRequest, errorFactory).mapContent<VisualMediaGroupPartContent>()
suspend fun BehaviourContext.waitMediaContent(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent(initRequest, errorFactory).mapContent<MediaContent>()

View File

@@ -5,6 +5,7 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations
import dev.inmo.micro_utils.coroutines.safelyWithoutExceptions
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
import dev.inmo.tgbotapi.extensions.utils.withContent
import dev.inmo.tgbotapi.extensions.utils.withContentOrNull
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage
import dev.inmo.tgbotapi.types.message.content.*
@@ -12,142 +13,138 @@ import dev.inmo.tgbotapi.types.update.abstracts.BaseSentMessageUpdate
import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.lowLevelRiskFeatureMessage
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.mapNotNull
typealias CommonMessageToCommonMessageMapper<T> = suspend CommonMessage<T>.() -> CommonMessage<T>?
@RiskFeature(lowLevelRiskFeatureMessage)
suspend inline fun <reified O : MessageContent> BehaviourContext.waitContentMessage(
suspend inline fun BehaviourContext.waitContentMessage(
initRequest: Request<*>? = null,
noinline errorFactory: NullableRequestBuilder<*> = { null }
): Flow<CommonMessage<O>> = expectFlow(
): Flow<CommonMessage<MessageContent>> = expectFlow(
initRequest,
errorFactory
) {
if (it !is BaseSentMessageUpdate) {
return@expectFlow emptyList()
}
listOfNotNull((it.data as? CommonMessage<*>) ?.withContent<O>())
listOfNotNull((it.data as? CommonMessage<*>))
}
internal inline fun <reified T : MessageContent> contentMessageConverter(
noinline mapper: CommonMessageToCommonMessageMapper<T>? = null
): suspend CommonMessage<MessageContent>.() -> CommonMessage<T>? = mapper ?.let {
{
if (content is T) {
@Suppress("UNCHECKED_CAST")
val message = (this as CommonMessage<T>)
safelyWithoutExceptions { mapper(message) }
} else {
null
}
}
} ?: {
@Suppress("UNCHECKED_CAST")
if (content is T) this as CommonMessage<T> else null
}
inline fun <reified T : MessageContent> Flow<CommonMessage<MessageContent>>.mapWithContent() = mapNotNull { it.withContentOrNull<T>() }
suspend fun BehaviourContext.waitAnyContentMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null },
) = waitContentMessage<MessageContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory)
suspend fun BehaviourContext.waitTextedContentMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null },
) = waitContentMessage(initRequest, errorFactory).mapWithContent<TextedContent>()
suspend fun BehaviourContext.waitContactMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<ContactContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<ContactContent>()
suspend fun BehaviourContext.waitDiceMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<DiceContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<DiceContent>()
suspend fun BehaviourContext.waitGameMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<GameContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<GameContent>()
suspend fun BehaviourContext.waitLocationMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<LocationContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<LocationContent>()
suspend fun BehaviourContext.waitLiveLocationMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<LiveLocationContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<LiveLocationContent>()
suspend fun BehaviourContext.waitStaticLocationMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<StaticLocationContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<StaticLocationContent>()
suspend fun BehaviourContext.waitPollMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<PollContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<PollContent>()
suspend fun BehaviourContext.waitTextMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<TextContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<TextContent>()
suspend fun BehaviourContext.waitVenueMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<VenueContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<VenueContent>()
suspend fun BehaviourContext.waitAudioMediaGroupContentMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<AudioMediaGroupPartContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<AudioMediaGroupPartContent>()
suspend fun BehaviourContext.waitDocumentMediaGroupContentMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<DocumentMediaGroupPartContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<DocumentMediaGroupPartContent>()
suspend fun BehaviourContext.waitMediaMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<MediaContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<MediaContent>()
suspend fun BehaviourContext.waitAnyMediaGroupContentMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<MediaGroupPartContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<MediaGroupPartContent>()
suspend fun BehaviourContext.waitVisualMediaGroupContentMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<VisualMediaGroupPartContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<VisualMediaGroupPartContent>()
suspend fun BehaviourContext.waitTextedMediaContentMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<TextedMediaContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<TextedMediaContent>()
suspend fun BehaviourContext.waitAnimationMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<AnimationContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<AnimationContent>()
suspend fun BehaviourContext.waitAudioMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<AudioContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<AudioContent>()
suspend fun BehaviourContext.waitDocumentMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<DocumentContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<DocumentContent>()
suspend fun BehaviourContext.waitPhotoMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<PhotoContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<PhotoContent>()
suspend fun BehaviourContext.waitStickerMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<StickerContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<StickerContent>()
suspend fun BehaviourContext.waitVideoMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<VideoContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<VideoContent>()
suspend fun BehaviourContext.waitVideoNoteMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<VideoNoteContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<VideoNoteContent>()
suspend fun BehaviourContext.waitVoiceMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<VoiceContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<VoiceContent>()
suspend fun BehaviourContext.waitInvoiceMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<InvoiceContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<InvoiceContent>()
suspend fun BehaviourContext.waitVisualContentMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<VisualMediaGroupPartContent>(initRequest, errorFactory)
) = waitContentMessage(initRequest, errorFactory).mapWithContent<VisualMediaGroupPartContent>()
suspend fun BehaviourContext.waitMediaContentMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage(initRequest, errorFactory).mapWithContent<MediaContent>()

View File

@@ -0,0 +1,107 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
import dev.inmo.tgbotapi.extensions.utils.whenMentionTextSource
import dev.inmo.tgbotapi.extensions.utils.whenTextMentionTextSource
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.Username
import dev.inmo.tgbotapi.types.chat.User
import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage
import dev.inmo.tgbotapi.types.message.content.MessageContent
import dev.inmo.tgbotapi.types.message.content.TextedContent
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filter
/**
* Check, that [TextedContent.textSources] contains:
*
* * Any [dev.inmo.tgbotapi.types.message.textsources.MentionTextSource] with [dev.inmo.tgbotapi.types.message.textsources.MentionTextSource.username]
* equal to [username]
* * Any [dev.inmo.tgbotapi.types.message.textsources.TextMentionTextSource] with [dev.inmo.tgbotapi.types.message.textsources.TextMentionTextSource.user]
* with the same [username]
*/
fun TextedContent.isWithMention(username: Username) = textSources.any {
it.whenMentionTextSource {
it.username == username
} ?: it.whenTextMentionTextSource {
it.user.username == username
} ?: false
}
/**
* Check, that [TextedContent.textSources] contains:
*
* * Any [dev.inmo.tgbotapi.types.message.textsources.TextMentionTextSource] with [dev.inmo.tgbotapi.types.message.textsources.TextMentionTextSource.user]
* with the same [userId]
*/
fun TextedContent.isWithTextMention(userId: UserId) = textSources.any {
it.whenTextMentionTextSource {
it.user.id == userId
} ?: false
}
/**
* Uses [isWithMention] with [user] [Username] (is presented) or [isWithTextMention] with [user] [UserId] to determine
* user mentioning in [this] [CommonMessage]
*/
fun TextedContent.isWithMention(user: User): Boolean = user.username ?.let { username -> isWithMention(username) } == true || isWithTextMention(user.id)
/**
* Uses [isWithMention] passing [username] as argument to take only messages with [username] mentions or text mentions
*/
fun Flow<TextedContent>.filterMentions(username: Username) = filter {
it.isWithMention(username)
}
/**
* Uses [isWithTextMention] passing [userId] as argument to take only messages with [userId] text mentions
*/
fun Flow<TextedContent>.filterTextMentions(userId: UserId) = filter {
it.isWithTextMention(userId)
}
/**
* Uses [isWithMention] passing [user] as argument to take only messages with [user] mentions or text mentions
*/
fun Flow<TextedContent>.filterMentions(user: User) = filter {
it.isWithMention(user)
}
/**
* Creates cold [Flow] with the messages with [TextedContent] where [username] has been mentioned
*
* @see filterMentions
* @see filterTextMentions
*/
suspend fun BehaviourContext.waitContentWithMentions (
username: Username,
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent(initRequest, errorFactory).mapContent<TextedContent>().filterMentions(username)
/**
* Creates cold [Flow] with the messages with [TextedContent] where [userId] has been mentioned with text
*
* @see filterTextMentions
* @see filterMentions
* @see dev.inmo.tgbotapi.types.message.textsources.TextMentionTextSource
*/
suspend fun BehaviourContext.waitContentWithTextMentions (
userId: UserId,
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitTextedContent(initRequest, errorFactory).filterTextMentions(userId)
/**
* Creates cold [Flow] with the messages with [TextedContent] where [user] has been mentioned as text or mentioned
* with text
*
* @see filterMentions
* @see filterTextMentions
*/
suspend fun BehaviourContext.waitContentWithMentions (
user: User,
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitTextedContent(initRequest, errorFactory).filterMentions(user)

View File

@@ -0,0 +1,82 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
import dev.inmo.tgbotapi.extensions.utils.whenMentionTextSource
import dev.inmo.tgbotapi.extensions.utils.whenTextMentionTextSource
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.Username
import dev.inmo.tgbotapi.types.chat.User
import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage
import dev.inmo.tgbotapi.types.message.content.TextedContent
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filter
fun CommonMessage<TextedContent>.isWithMention(username: Username) = content.isWithMention(username)
fun CommonMessage<TextedContent>.isWithTextMention(userId: UserId) = content.isWithTextMention(userId)
/**
* Uses [isWithMention] with [user] [Username] (is presented) or [isWithTextMention] with [user] [UserId] to determine
* user mentioning in [this] [CommonMessage]
*/
fun CommonMessage<TextedContent>.isWithMention(user: User): Boolean = content.isWithMention(user)
/**
* Uses [isWithMention] passing [username] as argument to take only messages with [username] mentions or text mentions
*/
fun Flow<CommonMessage<TextedContent>>.filterMentionsMessages(username: Username) = filter {
it.isWithMention(username)
}
/**
* Uses [isWithTextMention] passing [userId] as argument to take only messages with [userId] text mentions
*/
fun Flow<CommonMessage<TextedContent>>.filterTextMentionsMessages(userId: UserId) = filter {
it.isWithTextMention(userId)
}
/**
* Uses [isWithMention] passing [user] as argument to take only messages with [user] mentions or text mentions
*/
fun Flow<CommonMessage<TextedContent>>.filterMentionsMessages(user: User) = filter {
it.isWithMention(user)
}
/**
* Creates cold [Flow] with the messages with [TextedContent] where [username] has been mentioned
*
* @see filterMentions
* @see filterTextMentions
*/
suspend fun BehaviourContext.waitContentMessageWithMentions (
username: Username,
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage(initRequest, errorFactory).mapWithContent<TextedContent>().filterMentionsMessages(username)
/**
* Creates cold [Flow] with the messages with [TextedContent] where [userId] has been mentioned with text
*
* @see filterTextMentions
* @see filterMentions
* @see dev.inmo.tgbotapi.types.message.textsources.TextMentionTextSource
*/
suspend fun BehaviourContext.waitContentMessageWithTextMentions (
userId: UserId,
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitTextedContentMessage(initRequest, errorFactory).filterTextMentionsMessages(userId)
/**
* Creates cold [Flow] with the messages with [TextedContent] where [user] has been mentioned as text or mentioned
* with text
*
* @see filterMentions
* @see filterTextMentions
*/
suspend fun BehaviourContext.waitContentMessageWithMentions (
user: User,
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitTextedContentMessage(initRequest, errorFactory).filterMentionsMessages(user)

View File

@@ -248,6 +248,30 @@ suspend fun <BC : BehaviourContext> BC.onText(
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.onTextedContent(
initialFilter: CommonMessageFilter<TextedContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, TextedMessage, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in TextedMessage, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, TextedMessage>
) = onContentMessageWithType(
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,
@@ -631,3 +655,27 @@ suspend fun <BC : BehaviourContext> BC.onVisualContent(
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.onMediaContent(
initialFilter: CommonMessageFilter<MediaContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, MediaMessage, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in MediaMessage, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, MediaMessage>
) = onContentMessageWithType(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)

View File

@@ -0,0 +1,357 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
import dev.inmo.tgbotapi.extensions.behaviour_builder.CustomBehaviourContextAndTwoTypesReceiver
import dev.inmo.tgbotapi.extensions.behaviour_builder.CustomBehaviourContextAndTypeReceiver
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.isWithMention
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.isWithTextMention
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.behaviour_builder.utils.times
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.Username
import dev.inmo.tgbotapi.types.chat.User
import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage
import dev.inmo.tgbotapi.types.message.content.AnimationContent
import dev.inmo.tgbotapi.types.message.content.AudioContent
import dev.inmo.tgbotapi.types.message.content.DocumentContent
import dev.inmo.tgbotapi.types.message.content.MediaGroupContent
import dev.inmo.tgbotapi.types.message.content.MediaGroupPartContent
import dev.inmo.tgbotapi.types.message.content.PhotoContent
import dev.inmo.tgbotapi.types.message.content.TextContent
import dev.inmo.tgbotapi.types.message.content.TextedContent
import dev.inmo.tgbotapi.types.message.content.VideoContent
import dev.inmo.tgbotapi.types.message.content.VisualMediaGroupPartContent
import dev.inmo.tgbotapi.types.message.content.VoiceContent
import dev.inmo.tgbotapi.types.update.abstracts.Update
internal suspend inline fun <BC : BehaviourContext, reified T : TextedContent> BC.onMention(
username: Username,
initialFilter: CommonMessageFilter<T>? = null,
noinline subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<T>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<T>, Any> = AnyMarkerFactory(),
noinline scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<T>>
) = onContentMessageWithType<BC, T>(
initialFilter * {
it.content.isWithMention(username)
},
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
internal suspend inline fun <BC : BehaviourContext, reified T : TextedContent> BC.onTextMention(
userId: UserId,
initialFilter: CommonMessageFilter<T>? = null,
noinline subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<T>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<T>, Any> = AnyMarkerFactory(),
noinline scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<T>>
) = onContentMessageWithType<BC, T>(
initialFilter * {
it.content.isWithTextMention(userId)
},
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
internal suspend inline fun <BC : BehaviourContext, reified T : TextedContent> BC.onMention(
user: User,
initialFilter: CommonMessageFilter<T>? = null,
noinline subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<T>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<T>, Any> = AnyMarkerFactory(),
noinline scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<T>>
) = onContentMessageWithType<BC, T>(
initialFilter * {
it.content.isWithMention(user)
},
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
suspend fun <BC : BehaviourContext> BC.onMentionWithAnyContent(
username: Username,
initialFilter: CommonMessageFilter<TextedContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<TextedContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<TextedContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<TextedContent>>
) = onMention(username, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onTextMentionWithAnyContent(
userId: UserId,
initialFilter: CommonMessageFilter<TextedContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<TextedContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<TextedContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<TextedContent>>
) = onTextMention(userId, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onMentionWithAnyContent(
user: User,
initialFilter: CommonMessageFilter<TextedContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<TextedContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<TextedContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<TextedContent>>
) = onMention(user, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onMentionWithVoiceContent(
username: Username,
initialFilter: CommonMessageFilter<VoiceContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<VoiceContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<VoiceContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<VoiceContent>>
) = onMention(username, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onTextMentionWithVoiceContent(
userId: UserId,
initialFilter: CommonMessageFilter<VoiceContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<VoiceContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<VoiceContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<VoiceContent>>
) = onTextMention(userId, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onMentionWithVoiceContent(
user: User,
initialFilter: CommonMessageFilter<VoiceContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<VoiceContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<VoiceContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<VoiceContent>>
) = onMention(user, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onMentionWithMediaGroupContent(
username: Username,
initialFilter: CommonMessageFilter<MediaGroupContent<MediaGroupPartContent>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<MediaGroupContent<MediaGroupPartContent>>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<MediaGroupPartContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<MediaGroupContent<MediaGroupPartContent>>>
) = onMention(username, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onTextMentionWithMediaGroupContent(
userId: UserId,
initialFilter: CommonMessageFilter<MediaGroupContent<MediaGroupPartContent>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<MediaGroupContent<MediaGroupPartContent>>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<MediaGroupContent<MediaGroupPartContent>>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<MediaGroupContent<MediaGroupPartContent>>>
) = onTextMention(userId, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onMentionWithMediaGroupContent(
user: User,
initialFilter: CommonMessageFilter<MediaGroupContent<MediaGroupPartContent>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<MediaGroupContent<MediaGroupPartContent>>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<MediaGroupContent<MediaGroupPartContent>>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<MediaGroupContent<MediaGroupPartContent>>>
) = onMention(user, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onMentionWithMediaGroupPartContent(
username: Username,
initialFilter: CommonMessageFilter<MediaGroupPartContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<MediaGroupPartContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<MediaGroupPartContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<MediaGroupPartContent>>
) = onMention(username, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onTextMentionWithMediaGroupPartContent(
userId: UserId,
initialFilter: CommonMessageFilter<MediaGroupPartContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<MediaGroupPartContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<MediaGroupPartContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<MediaGroupPartContent>>
) = onTextMention(userId, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onMentionWithMediaGroupPartContent(
user: User,
initialFilter: CommonMessageFilter<MediaGroupPartContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<MediaGroupPartContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<MediaGroupPartContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<MediaGroupPartContent>>
) = onMention(user, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onMentionWithAudioContent(
username: Username,
initialFilter: CommonMessageFilter<AudioContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<AudioContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<AudioContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<AudioContent>>
) = onMention(username, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onTextMentionWithAudioContent(
userId: UserId,
initialFilter: CommonMessageFilter<AudioContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<AudioContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<AudioContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<AudioContent>>
) = onTextMention(userId, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onMentionWithAudioContent(
user: User,
initialFilter: CommonMessageFilter<AudioContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<AudioContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<AudioContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<AudioContent>>
) = onMention(user, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onMentionWithDocumentContent(
username: Username,
initialFilter: CommonMessageFilter<DocumentContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<DocumentContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<DocumentContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<DocumentContent>>
) = onMention(username, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onTextMentionWithDocumentContent(
userId: UserId,
initialFilter: CommonMessageFilter<DocumentContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<DocumentContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<DocumentContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<DocumentContent>>
) = onTextMention(userId, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onMentionWithDocumentContent(
user: User,
initialFilter: CommonMessageFilter<DocumentContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<DocumentContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<DocumentContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<DocumentContent>>
) = onMention(user, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onMentionWithVisualMediaGroupPartContent(
username: Username,
initialFilter: CommonMessageFilter<VisualMediaGroupPartContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<VisualMediaGroupPartContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<VisualMediaGroupPartContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<VisualMediaGroupPartContent>>
) = onMention(username, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onTextMentionWithVisualMediaGroupPartContent(
userId: UserId,
initialFilter: CommonMessageFilter<VisualMediaGroupPartContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<VisualMediaGroupPartContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<VisualMediaGroupPartContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<VisualMediaGroupPartContent>>
) = onTextMention(userId, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onMentionWithVisualMediaGroupPartContent(
user: User,
initialFilter: CommonMessageFilter<VisualMediaGroupPartContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<VisualMediaGroupPartContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<VisualMediaGroupPartContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<VisualMediaGroupPartContent>>
) = onMention(user, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onMentionWithVideoContent(
username: Username,
initialFilter: CommonMessageFilter<VideoContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<VideoContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<VideoContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<VideoContent>>
) = onMention(username, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onTextMentionWithVideoContent(
userId: UserId,
initialFilter: CommonMessageFilter<VideoContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<VideoContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<VideoContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<VideoContent>>
) = onTextMention(userId, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onMentionWithVideoContent(
user: User,
initialFilter: CommonMessageFilter<VideoContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<VideoContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<VideoContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<VideoContent>>
) = onMention(user, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onMentionWithPhotoContent(
username: Username,
initialFilter: CommonMessageFilter<PhotoContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<PhotoContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<PhotoContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<PhotoContent>>
) = onMention(username, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onTextMentionWithPhotoContent(
userId: UserId,
initialFilter: CommonMessageFilter<PhotoContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<PhotoContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<PhotoContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<PhotoContent>>
) = onTextMention(userId, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onMentionWithPhotoContent(
user: User,
initialFilter: CommonMessageFilter<PhotoContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<PhotoContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<PhotoContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<PhotoContent>>
) = onMention(user, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onMentionWithAnimationContent(
username: Username,
initialFilter: CommonMessageFilter<AnimationContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<AnimationContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<AnimationContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<AnimationContent>>
) = onMention(username, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onTextMentionWithAnimationContent(
userId: UserId,
initialFilter: CommonMessageFilter<AnimationContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<AnimationContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<AnimationContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<AnimationContent>>
) = onTextMention(userId, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onMentionWithAnimationContent(
user: User,
initialFilter: CommonMessageFilter<AnimationContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<AnimationContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<AnimationContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<AnimationContent>>
) = onMention(user, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onMentionWithTextContent(
username: Username,
initialFilter: CommonMessageFilter<TextContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<TextContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<TextContent>>
) = onMention(username, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onTextMentionWithTextContent(
userId: UserId,
initialFilter: CommonMessageFilter<TextContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<TextContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<TextContent>>
) = onTextMention(userId, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun <BC : BehaviourContext> BC.onMentionWithTextContent(
user: User,
initialFilter: CommonMessageFilter<TextContent>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, CommonMessage<TextContent>, Update>? = null,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = AnyMarkerFactory(),
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<TextContent>>
) = onMention(user, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)

View File

@@ -21,6 +21,11 @@ import kotlinx.serialization.encoding.Encoder
* @see ByteArray.asMultipartFile
* @see ByteReadChannel.asMultipartFile
* @see ByteReadChannelAllocator.asMultipartFile
*
* @see fromInput
* @see fromFile
* @see fromId
* @see fromUrl
*/
@Serializable(InputFileSerializer::class)
sealed class InputFile {
@@ -29,9 +34,24 @@ sealed class InputFile {
companion object {
operator fun invoke(file: MPPFile) = file.asMultipartFile()
/**
* Creates [MultipartFile] based on incoming [filename] and [inputSource]
*/
fun fromInput(filename: String, inputSource: () -> Input) = MultipartFile(filename, inputSource)
/**
* Creates [MultipartFile] based on incoming [MPPFile] (common File in java, for example)
*/
fun fromFile(file: MPPFile) = invoke(file)
/**
* Creates [FileId] from the incomming [id] [String] with believe that it is [FileId]
*/
fun fromId(id: String) = FileId(id)
/**
* Creates [FileUrl] from the incomming [url] [String]
*/
fun fromUrl(url: String) = FileUrl(url)
}
}

View File

@@ -22,7 +22,7 @@ data class StickerSurrogate(
val height: Int,
val is_animated: Boolean? = null,
val is_video: Boolean? = null,
val thumb: PhotoSize? = null,
val thumbnail: PhotoSize? = null,
val emoji: String? = null,
val set_name: StickerSetName? = null,
val premium_animation: File? = null,
@@ -43,6 +43,7 @@ sealed interface Sticker : TelegramMediaFile, SizedMediaFile, ThumbedMediaFile {
get() = false
val isVideo
get() = false
val type: StickerType
fun asInputSticker(emojis: List<String> = emoji ?.let { listOf(it) } ?: error("Unable to create input sticker without emojis")): InputSticker
}
@@ -62,7 +63,7 @@ object StickerSerializer : KSerializer<Sticker> {
surrogate.file_unique_id,
surrogate.width,
surrogate.height,
surrogate.thumb,
surrogate.thumbnail,
surrogate.emoji,
surrogate.set_name,
surrogate.premium_animation,
@@ -73,7 +74,7 @@ object StickerSerializer : KSerializer<Sticker> {
surrogate.file_unique_id,
surrogate.width,
surrogate.height,
surrogate.thumb,
surrogate.thumbnail,
surrogate.emoji,
surrogate.set_name,
surrogate.premium_animation,
@@ -84,7 +85,7 @@ object StickerSerializer : KSerializer<Sticker> {
surrogate.file_unique_id,
surrogate.width,
surrogate.height,
surrogate.thumb,
surrogate.thumbnail,
surrogate.emoji,
surrogate.set_name,
surrogate.premium_animation,
@@ -98,7 +99,7 @@ object StickerSerializer : KSerializer<Sticker> {
surrogate.width,
surrogate.height,
surrogate.mask_position,
surrogate.thumb,
surrogate.thumbnail,
surrogate.emoji,
surrogate.set_name,
surrogate.file_size
@@ -109,7 +110,7 @@ object StickerSerializer : KSerializer<Sticker> {
surrogate.width,
surrogate.height,
surrogate.mask_position,
surrogate.thumb,
surrogate.thumbnail,
surrogate.emoji,
surrogate.set_name,
surrogate.file_size
@@ -120,7 +121,7 @@ object StickerSerializer : KSerializer<Sticker> {
surrogate.width,
surrogate.height,
surrogate.mask_position,
surrogate.thumb,
surrogate.thumbnail,
surrogate.emoji,
surrogate.set_name,
surrogate.file_size
@@ -133,7 +134,7 @@ object StickerSerializer : KSerializer<Sticker> {
surrogate.width,
surrogate.height,
surrogate.custom_emoji_id ?: error("For custom emoji stickers field custom_emoji_id should be presented"),
surrogate.thumb,
surrogate.thumbnail,
surrogate.emoji,
surrogate.set_name,
surrogate.file_size,
@@ -145,7 +146,7 @@ object StickerSerializer : KSerializer<Sticker> {
surrogate.width,
surrogate.height,
surrogate.custom_emoji_id ?: error("For custom emoji stickers field custom_emoji_id should be presented"),
surrogate.thumb,
surrogate.thumbnail,
surrogate.emoji,
surrogate.set_name,
surrogate.file_size,
@@ -157,7 +158,7 @@ object StickerSerializer : KSerializer<Sticker> {
surrogate.width,
surrogate.height,
surrogate.custom_emoji_id ?: error("For custom emoji stickers field custom_emoji_id should be presented"),
surrogate.thumb,
surrogate.thumbnail,
surrogate.emoji,
surrogate.set_name,
surrogate.file_size,
@@ -169,7 +170,7 @@ object StickerSerializer : KSerializer<Sticker> {
surrogate.file_unique_id,
surrogate.width,
surrogate.height,
surrogate.thumb,
surrogate.thumbnail,
surrogate.emoji,
surrogate.set_name,
surrogate.file_size,
@@ -178,13 +179,35 @@ object StickerSerializer : KSerializer<Sticker> {
surrogate.is_video == true -> StickerFormat.Video
else -> StickerFormat.Static
},
surrogate.type,
json
)
}
}
override fun serialize(encoder: Encoder, value: Sticker) {
TODO("Not yet implemented")
with(value) {
StickerSurrogate.serializer().serialize(
encoder,
StickerSurrogate(
fileId,
fileUniqueId,
type,
width,
height,
isAnimated,
isVideo,
thumbnail,
emoji,
stickerSetName,
(this as? RegularSticker) ?.premiumAnimationFile,
(this as? MaskSticker) ?.maskPosition,
(this as? CustomEmojiSticker) ?.customEmojiId,
fileSize,
(this as? CustomEmojiSticker) ?.needsRepainting ?: false
)
)
}
}
}
@@ -210,6 +233,9 @@ sealed interface AnimatedSticker : Sticker {
sealed interface RegularSticker : Sticker {
val premiumAnimationFile: File?
override val type: StickerType.Regular
get() = StickerType.Regular
override fun asInputSticker(emojis: List<String>) = InputSticker.WithKeywords.Regular(
fileId,
emojis,
@@ -241,6 +267,11 @@ data class RegularSimpleSticker(
@SerialName(stickerFormatField)
@EncodeDefault
override val stickerFormat: StickerFormat = StickerFormat.Static
@SerialName(stickerTypeField)
@Serializable(StickerType.Serializer::class)
@EncodeDefault
override val type: StickerType.Regular
get() = StickerType.Regular
}
@Serializable
@@ -263,7 +294,13 @@ data class RegularAnimatedSticker(
override val premiumAnimationFile: File? = null,
@SerialName(fileSizeField)
override val fileSize: Long? = null,
) : RegularSticker, AnimatedSticker
) : RegularSticker, AnimatedSticker {
@SerialName(stickerTypeField)
@Serializable(StickerType.Serializer::class)
@EncodeDefault
override val type: StickerType.Regular
get() = StickerType.Regular
}
@Serializable
data class RegularVideoSticker(
@SerialName(fileIdField)
@@ -284,13 +321,22 @@ data class RegularVideoSticker(
override val premiumAnimationFile: File? = null,
@SerialName(fileSizeField)
override val fileSize: Long? = null,
) : RegularSticker, VideoSticker
) : RegularSticker, VideoSticker {
@SerialName(stickerTypeField)
@Serializable(StickerType.Serializer::class)
@EncodeDefault
override val type: StickerType.Regular
get() = StickerType.Regular
}
@Serializable
sealed interface MaskSticker : Sticker {
val maskPosition: MaskPosition?
override val type: StickerType.Mask
get() = StickerType.Mask
override fun asInputSticker(emojis: List<String>) = InputSticker.Mask(
fileId,
emojis,
@@ -321,6 +367,12 @@ data class MaskSimpleSticker(
@SerialName(stickerFormatField)
@EncodeDefault
override val stickerFormat: StickerFormat = StickerFormat.Static
@SerialName(stickerTypeField)
@Serializable(StickerType.Serializer::class)
@EncodeDefault
override val type: StickerType.Mask
get() = StickerType.Mask
}
@Serializable
data class MaskAnimatedSticker(
@@ -342,7 +394,13 @@ data class MaskAnimatedSticker(
override val stickerSetName: StickerSetName? = null,
@SerialName(fileSizeField)
override val fileSize: Long? = null,
) : MaskSticker, AnimatedSticker
) : MaskSticker, AnimatedSticker {
@SerialName(stickerTypeField)
@Serializable(StickerType.Serializer::class)
@EncodeDefault
override val type: StickerType.Mask
get() = StickerType.Mask
}
@Serializable
data class MaskVideoSticker(
@SerialName(fileIdField)
@@ -363,13 +421,22 @@ data class MaskVideoSticker(
override val stickerSetName: StickerSetName? = null,
@SerialName(fileSizeField)
override val fileSize: Long? = null,
) : MaskSticker, VideoSticker
) : MaskSticker, VideoSticker {
@SerialName(stickerTypeField)
@Serializable(StickerType.Serializer::class)
@EncodeDefault
override val type: StickerType.Mask
get() = StickerType.Mask
}
@Serializable
sealed interface CustomEmojiSticker : Sticker {
val customEmojiId: CustomEmojiId
val needsRepainting: Boolean
override val type: StickerType.CustomEmoji
get() = StickerType.CustomEmoji
override fun asInputSticker(emojis: List<String>) = InputSticker.WithKeywords.CustomEmoji(
fileId,
emojis,
@@ -403,6 +470,12 @@ data class CustomEmojiSimpleSticker(
@SerialName(stickerFormatField)
@EncodeDefault
override val stickerFormat: StickerFormat = StickerFormat.Static
@SerialName(stickerTypeField)
@Serializable(StickerType.Serializer::class)
@EncodeDefault
override val type: StickerType.CustomEmoji
get() = StickerType.CustomEmoji
}
@Serializable
data class CustomEmojiAnimatedSticker(
@@ -426,7 +499,13 @@ data class CustomEmojiAnimatedSticker(
override val fileSize: Long? = null,
@SerialName(needsRepaintingField)
override val needsRepainting: Boolean = false,
) : CustomEmojiSticker, AnimatedSticker
) : CustomEmojiSticker, AnimatedSticker {
@SerialName(stickerTypeField)
@Serializable(StickerType.Serializer::class)
@EncodeDefault
override val type: StickerType.CustomEmoji
get() = StickerType.CustomEmoji
}
@Serializable
data class CustomEmojiVideoSticker(
@SerialName(fileIdField)
@@ -449,7 +528,13 @@ data class CustomEmojiVideoSticker(
override val fileSize: Long? = null,
@SerialName(needsRepaintingField)
override val needsRepainting: Boolean = false,
) : CustomEmojiSticker, VideoSticker
) : CustomEmojiSticker, VideoSticker {
@SerialName(stickerTypeField)
@Serializable(StickerType.Serializer::class)
@EncodeDefault
override val type: StickerType.CustomEmoji
get() = StickerType.CustomEmoji
}
@Serializable
data class UnknownSticker(
@@ -471,6 +556,9 @@ data class UnknownSticker(
override val fileSize: Long? = null,
@SerialName(stickerFormatField)
override val stickerFormat: StickerFormat = StickerFormat.Static,
@SerialName(stickerTypeField)
@Serializable(StickerType.Serializer::class)
override val type: StickerType = StickerType.Regular,
val raw: JsonElement
) : Sticker {
override fun asInputSticker(emojis: List<String>) = InputSticker.WithKeywords.Regular(

View File

@@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.types.message.content
import dev.inmo.tgbotapi.abstracts.SpoilerableData
import dev.inmo.tgbotapi.abstracts.TextedInput
import dev.inmo.tgbotapi.utils.internal.ClassCastsIncluded
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.types.ChatIdentifier
@@ -51,6 +52,18 @@ sealed interface MessageContent: ResendableContent {
additionalBuilder()
}
polymorphic(TextedContent::class) {
subclass(TextContent::class)
subclass(VoiceContent::class)
subclass(MediaGroupContent::class)
subclass(AudioContent::class)
subclass(DocumentContent::class)
subclass(VideoContent::class)
subclass(PhotoContent::class)
subclass(AnimationContent::class)
}
polymorphic(MediaCollectionContent::class) {
subclass(PhotoContent::class)
@@ -115,6 +128,11 @@ sealed interface MediaCollectionContent<T: TelegramMediaFile>: MessageContent, M
val mediaCollection: List<T>
}
/**
* All the subtypes of this content will have [text] and [textSources] fields
*/
sealed interface TextedContent : MessageContent, TextedInput
sealed interface MediaContent: MessageContent {
val media: TelegramMediaFile
fun asTelegramMedia(): TelegramMedia

View File

@@ -22,7 +22,7 @@ sealed interface DocumentMediaGroupPartContent : MediaGroupPartContent {
override fun toMediaGroupMemberTelegramMedia(): DocumentMediaGroupMemberTelegramMedia
}
sealed interface TextedMediaContent : MediaContent, TextedInput
sealed interface TextedMediaContent : TextedContent, MediaContent
sealed interface MediaGroupCollectionContent<T : MediaGroupPartContent> : TextedMediaContent {
@Serializable

View File

@@ -15,7 +15,7 @@ import kotlinx.serialization.Serializable
data class TextContent(
override val text: String,
override val textSources: TextSourcesList = emptyList(),
) : MessageContent, TextedInput {
) : TextedContent {
override fun createResend(
chatId: ChatIdentifier,
messageThreadId: MessageThreadId?,

View File

@@ -2,6 +2,8 @@ package dev.inmo.tgbotapi.types.message.content
import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage
typealias TextedMessage = CommonMessage<TextedContent>
typealias InvoiceMessage = CommonMessage<InvoiceContent>
typealias VenueMessage = CommonMessage<VenueContent>
typealias GameMessage = CommonMessage<GameContent>

View File

@@ -329,6 +329,7 @@ import dev.inmo.tgbotapi.types.message.content.SpoilerableMediaContent
import dev.inmo.tgbotapi.types.message.content.StaticLocationContent
import dev.inmo.tgbotapi.types.message.content.StickerContent
import dev.inmo.tgbotapi.types.message.content.TextContent
import dev.inmo.tgbotapi.types.message.content.TextedContent
import dev.inmo.tgbotapi.types.message.content.TextedMediaContent
import dev.inmo.tgbotapi.types.message.content.VenueContent
import dev.inmo.tgbotapi.types.message.content.VideoContent
@@ -3712,6 +3713,15 @@ public inline fun <T>
ResendableContent.ifMediaCollectionContent(block: (MediaCollectionContent<TelegramMediaFile>) -> T):
T? = mediaCollectionContentOrNull() ?.let(block)
public inline fun ResendableContent.textedContentOrNull(): TextedContent? = this as?
dev.inmo.tgbotapi.types.message.content.TextedContent
public inline fun ResendableContent.textedContentOrThrow(): TextedContent = this as
dev.inmo.tgbotapi.types.message.content.TextedContent
public inline fun <T> ResendableContent.ifTextedContent(block: (TextedContent) -> T): T? =
textedContentOrNull() ?.let(block)
public inline fun ResendableContent.mediaContentOrNull(): MediaContent? = this as?
dev.inmo.tgbotapi.types.message.content.MediaContent