mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2026-08-20 08:06:21 +00:00
improve richblocks api and let rich message content to be correctly resendable if there are no any media block inside
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
package dev.inmo.tgbotapi.types.message.content
|
||||
|
||||
import dev.inmo.tgbotapi.requests.ForwardMessage
|
||||
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||
import dev.inmo.tgbotapi.requests.send.CopyMessage
|
||||
import dev.inmo.tgbotapi.requests.send.SendRichMessage
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.business_connection.BusinessConnectionId
|
||||
@@ -9,8 +11,14 @@ import dev.inmo.tgbotapi.types.chat.Chat
|
||||
import dev.inmo.tgbotapi.types.message.SuggestedPostParameters
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.ChatContentMessage
|
||||
import dev.inmo.tgbotapi.types.rich.InputRichMessageMarkdown
|
||||
import dev.inmo.tgbotapi.types.rich.RichBlock
|
||||
import dev.inmo.tgbotapi.types.rich.RichBlockAudio
|
||||
import dev.inmo.tgbotapi.types.rich.RichBlockMedia
|
||||
import dev.inmo.tgbotapi.types.rich.RichBlockPhoto
|
||||
import dev.inmo.tgbotapi.types.rich.RichBlockVideo
|
||||
import dev.inmo.tgbotapi.types.rich.RichTextInfo
|
||||
import dev.inmo.tgbotapi.types.rich.markdown
|
||||
import dev.inmo.tgbotapi.types.rich.search
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@@ -32,19 +40,39 @@ data class RichMessageContent(
|
||||
replyParameters: ReplyParameters?,
|
||||
replyMarkup: KeyboardMarkup?
|
||||
): Request<ChatContentMessage<RichMessageContent>> {
|
||||
return SendRichMessage(
|
||||
chatId = chatId,
|
||||
richMessage = InputRichMessageMarkdown(richMessage.markdown, isRtl = richMessage.isRtl),
|
||||
threadId = messageThreadId,
|
||||
directMessageThreadId = directMessageThreadId,
|
||||
businessConnectionId = businessConnectionId,
|
||||
disableNotification = disableNotification,
|
||||
protectContent = protectContent,
|
||||
allowPaidBroadcast = allowPaidBroadcast,
|
||||
effectId = effectId,
|
||||
suggestedPostParameters = suggestedPostParameters,
|
||||
replyParameters = replyParameters,
|
||||
replyMarkup = replyMarkup
|
||||
)
|
||||
val isThereMedia = richMessage.blocks.any {
|
||||
it.search {
|
||||
this is RichBlockMedia
|
||||
} != null
|
||||
}
|
||||
return if (isThereMedia) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
ForwardMessage(
|
||||
chat.id,
|
||||
toChatId = chatId,
|
||||
messageId = messageId,
|
||||
threadId = messageThreadId,
|
||||
directMessageThreadId = directMessageThreadId,
|
||||
disableNotification = disableNotification,
|
||||
protectContent = protectContent,
|
||||
effectId = effectId,
|
||||
suggestedPostParameters = suggestedPostParameters,
|
||||
) as Request<ChatContentMessage<RichMessageContent>>
|
||||
} else {
|
||||
SendRichMessage(
|
||||
chatId = chatId,
|
||||
richMessage = InputRichMessageMarkdown(richMessage.markdown, isRtl = richMessage.isRtl),
|
||||
threadId = messageThreadId,
|
||||
directMessageThreadId = directMessageThreadId,
|
||||
businessConnectionId = businessConnectionId,
|
||||
disableNotification = disableNotification,
|
||||
protectContent = protectContent,
|
||||
allowPaidBroadcast = allowPaidBroadcast,
|
||||
effectId = effectId,
|
||||
suggestedPostParameters = suggestedPostParameters,
|
||||
replyParameters = replyParameters,
|
||||
replyMarkup = replyMarkup
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package dev.inmo.tgbotapi.types.rich
|
||||
|
||||
import dev.inmo.tgbotapi.requests.abstracts.FileId
|
||||
import dev.inmo.tgbotapi.types.files.TelegramMediaFile
|
||||
import dev.inmo.tgbotapi.types.typeField
|
||||
import dev.inmo.tgbotapi.utils.internal.ClassCastsIncluded
|
||||
import kotlinx.serialization.DeserializationStrategy
|
||||
@@ -30,6 +32,39 @@ sealed interface RichBlock {
|
||||
val html: String
|
||||
}
|
||||
|
||||
@Serializable(RichBlockSerializer::class)
|
||||
sealed interface RichBlockMedia : RichBlock {
|
||||
val media: TelegramMediaFile
|
||||
val caption: RichBlockCaption?
|
||||
}
|
||||
|
||||
/**
|
||||
* The nested [RichBlock]s directly contained by this block, or an empty list for leaf blocks. Container blocks
|
||||
* ([RichBlockList] via its [RichBlockListItem.blocks], [RichBlockBlockQuotation], [RichBlockCollage],
|
||||
* [RichBlockSlideshow] and [RichBlockDetails]) expose their children here.
|
||||
*/
|
||||
val RichBlock.subBlocks: List<RichBlock>
|
||||
get() = when (this) {
|
||||
is RichBlockList -> items.flatMap { it.blocks }
|
||||
is RichBlockBlockQuotation -> blocks
|
||||
is RichBlockCollage -> blocks
|
||||
is RichBlockSlideshow -> blocks
|
||||
is RichBlockDetails -> blocks
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
/**
|
||||
* Walks this [RichBlock] and all of its [subBlocks] recursively (depth-first, this block first) and returns the first
|
||||
* block for which [block] returns `true`, or `null` if none matches.
|
||||
*/
|
||||
fun RichBlock.search(block: RichBlock.() -> Boolean): RichBlock? {
|
||||
if (block()) return this
|
||||
for (child in subBlocks) {
|
||||
child.search(block)?.let { return it }
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
object RichBlockSerializer : JsonContentPolymorphicSerializer<RichBlock>(RichBlock::class) {
|
||||
override fun selectDeserializer(element: JsonElement): DeserializationStrategy<RichBlock> {
|
||||
return when (val type = element.jsonObject[typeField]?.jsonPrimitive?.content) {
|
||||
|
||||
@@ -10,6 +10,7 @@ import dev.inmo.tgbotapi.types.expressionField
|
||||
import dev.inmo.tgbotapi.types.files.AnimationFile
|
||||
import dev.inmo.tgbotapi.types.files.AudioFile
|
||||
import dev.inmo.tgbotapi.types.files.PhotoFile
|
||||
import dev.inmo.tgbotapi.types.files.TelegramMediaFile
|
||||
import dev.inmo.tgbotapi.types.files.VideoFile
|
||||
import dev.inmo.tgbotapi.types.files.VoiceFile
|
||||
import dev.inmo.tgbotapi.types.hasSpoilerField
|
||||
@@ -537,8 +538,8 @@ data class RichBlockAnimation(
|
||||
@SerialName(hasSpoilerField)
|
||||
val hasSpoiler: Boolean? = null,
|
||||
@SerialName(captionField)
|
||||
val caption: RichBlockCaption? = null
|
||||
) : RichBlock {
|
||||
override val caption: RichBlockCaption? = null
|
||||
) : RichBlockMedia {
|
||||
@EncodeDefault
|
||||
@SerialName(typeField)
|
||||
override val type: String = TYPE
|
||||
@@ -546,6 +547,9 @@ data class RichBlockAnimation(
|
||||
override val markdown: String = markdown(animation, caption)
|
||||
override val html: String = html(animation, hasSpoiler, caption)
|
||||
|
||||
override val media: TelegramMediaFile
|
||||
get() = animation
|
||||
|
||||
companion object {
|
||||
const val TYPE = "animation"
|
||||
fun markdown(animation: AnimationFile, caption: RichBlockCaption?): String =
|
||||
@@ -565,14 +569,16 @@ data class RichBlockAudio(
|
||||
@SerialName(audioField)
|
||||
val audio: AudioFile,
|
||||
@SerialName(captionField)
|
||||
val caption: RichBlockCaption? = null
|
||||
) : RichBlock {
|
||||
override val caption: RichBlockCaption? = null
|
||||
) : RichBlockMedia {
|
||||
@EncodeDefault
|
||||
@SerialName(typeField)
|
||||
override val type: String = TYPE
|
||||
|
||||
override val markdown: String = markdown(audio, caption)
|
||||
override val html: String = html(audio, caption)
|
||||
override val media: TelegramMediaFile
|
||||
get() = audio
|
||||
|
||||
companion object {
|
||||
const val TYPE = "audio"
|
||||
@@ -595,14 +601,16 @@ data class RichBlockPhoto(
|
||||
@SerialName(hasSpoilerField)
|
||||
val hasSpoiler: Boolean? = null,
|
||||
@SerialName(captionField)
|
||||
val caption: RichBlockCaption? = null
|
||||
) : RichBlock {
|
||||
override val caption: RichBlockCaption? = null
|
||||
) : RichBlockMedia {
|
||||
@EncodeDefault
|
||||
@SerialName(typeField)
|
||||
override val type: String = TYPE
|
||||
|
||||
override val markdown: String = markdown(photo, caption)
|
||||
override val html: String = html(photo, hasSpoiler, caption)
|
||||
override val media: TelegramMediaFile
|
||||
get() = photo
|
||||
|
||||
companion object {
|
||||
const val TYPE = "photo"
|
||||
@@ -625,14 +633,16 @@ data class RichBlockVideo(
|
||||
@SerialName(hasSpoilerField)
|
||||
val hasSpoiler: Boolean? = null,
|
||||
@SerialName(captionField)
|
||||
val caption: RichBlockCaption? = null
|
||||
) : RichBlock {
|
||||
override val caption: RichBlockCaption? = null
|
||||
) : RichBlockMedia {
|
||||
@EncodeDefault
|
||||
@SerialName(typeField)
|
||||
override val type: String = TYPE
|
||||
|
||||
override val markdown: String = markdown(video, caption)
|
||||
override val html: String = html(video, hasSpoiler, caption)
|
||||
override val media: TelegramMediaFile
|
||||
get() = video
|
||||
|
||||
companion object {
|
||||
const val TYPE = "video"
|
||||
@@ -653,14 +663,16 @@ data class RichBlockVoiceNote(
|
||||
@SerialName(voiceNoteField)
|
||||
val voiceNote: VoiceFile,
|
||||
@SerialName(captionField)
|
||||
val caption: RichBlockCaption? = null
|
||||
) : RichBlock {
|
||||
override val caption: RichBlockCaption? = null
|
||||
) : RichBlockMedia {
|
||||
@EncodeDefault
|
||||
@SerialName(typeField)
|
||||
override val type: String = TYPE
|
||||
|
||||
override val markdown: String = markdown(voiceNote, caption)
|
||||
override val html: String = html(voiceNote, caption)
|
||||
override val media: TelegramMediaFile
|
||||
get() = voiceNote
|
||||
|
||||
companion object {
|
||||
const val TYPE = "voice_note"
|
||||
|
||||
Reference in New Issue
Block a user