mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2024-12-22 16:47:13 +00:00
add support of expandable blockquote
This commit is contained in:
parent
93e06a5765
commit
e403bbca0b
@ -32,6 +32,7 @@ internal data class RawMessageEntity(
|
||||
"phone_number" -> 1
|
||||
"bold" -> 1
|
||||
"blockquote" -> 0
|
||||
"expandable_blockquote" -> 0
|
||||
"italic" -> 1
|
||||
"text_mention" -> 1
|
||||
"strikethrough" -> 1
|
||||
@ -66,6 +67,7 @@ internal fun RawMessageEntity.asTextSource(
|
||||
"phone_number" -> PhoneNumberTextSource(sourceSubstring, subPartsWithRegulars)
|
||||
"bold" -> BoldTextSource(sourceSubstring, subPartsWithRegulars)
|
||||
"blockquote" -> BlockquoteTextSource(sourceSubstring, subPartsWithRegulars)
|
||||
"expandable_blockquote" -> ExpandableBlockquoteTextSource(sourceSubstring, subPartsWithRegulars)
|
||||
"italic" -> ItalicTextSource(sourceSubstring, subPartsWithRegulars)
|
||||
"code" -> CodeTextSource(sourceSubstring)
|
||||
"pre" -> PreTextSource(sourceSubstring, language)
|
||||
@ -186,6 +188,7 @@ internal fun TextSource.toRawMessageEntities(offset: Int = 0): List<RawMessageEn
|
||||
is PhoneNumberTextSource -> RawMessageEntity("phone_number", offset, length)
|
||||
is BoldTextSource -> RawMessageEntity("bold", offset, length)
|
||||
is BlockquoteTextSource -> RawMessageEntity("blockquote", offset, length)
|
||||
is ExpandableBlockquoteTextSource -> RawMessageEntity("expandable_blockquote", offset, length)
|
||||
is ItalicTextSource -> RawMessageEntity("italic", offset, length)
|
||||
is CodeTextSource -> RawMessageEntity("code", offset, length)
|
||||
is PreTextSource -> RawMessageEntity("pre", offset, length, language = language)
|
||||
|
@ -31,20 +31,21 @@ data class AnimationContent(
|
||||
replyParameters: ReplyParameters?,
|
||||
replyMarkup: KeyboardMarkup?
|
||||
): Request<ContentMessage<AnimationContent>> = SendAnimation(
|
||||
chatId,
|
||||
media.fileId,
|
||||
media.thumbnail ?.fileId,
|
||||
textSources,
|
||||
spoilered,
|
||||
media.duration,
|
||||
media.width,
|
||||
media.height,
|
||||
messageThreadId,
|
||||
businessConnectionId,
|
||||
disableNotification,
|
||||
protectContent,
|
||||
replyParameters,
|
||||
replyMarkup
|
||||
chatId = chatId,
|
||||
animation = media.fileId,
|
||||
thumbnail = media.thumbnail ?.fileId,
|
||||
entities = textSources,
|
||||
showCaptionAboveMedia = showCaptionAboveMedia,
|
||||
spoilered = spoilered,
|
||||
duration = media.duration,
|
||||
width = media.width,
|
||||
height = media.height,
|
||||
threadId = messageThreadId,
|
||||
businessConnectionId = businessConnectionId,
|
||||
disableNotification = disableNotification,
|
||||
protectContent = protectContent,
|
||||
replyParameters = replyParameters,
|
||||
replyMarkup = replyMarkup
|
||||
)
|
||||
|
||||
override fun asTelegramMedia(): TelegramMediaAnimation = TelegramMediaAnimation(
|
||||
|
@ -33,16 +33,17 @@ data class PhotoContent(
|
||||
replyParameters: ReplyParameters?,
|
||||
replyMarkup: KeyboardMarkup?
|
||||
): Request<ContentMessage<PhotoContent>> = SendPhoto(
|
||||
chatId,
|
||||
media.fileId,
|
||||
textSources,
|
||||
spoilered,
|
||||
messageThreadId,
|
||||
businessConnectionId,
|
||||
disableNotification,
|
||||
protectContent,
|
||||
replyParameters,
|
||||
replyMarkup
|
||||
chatId = chatId,
|
||||
photo = media.fileId,
|
||||
entities = textSources,
|
||||
showCaptionAboveMedia = showCaptionAboveMedia,
|
||||
spoilered = spoilered,
|
||||
threadId = messageThreadId,
|
||||
businessConnectionId = businessConnectionId,
|
||||
disableNotification = disableNotification,
|
||||
protectContent = protectContent,
|
||||
replyParameters = replyParameters,
|
||||
replyMarkup = replyMarkup
|
||||
)
|
||||
|
||||
override fun toMediaGroupMemberTelegramMedia(): TelegramMediaPhoto = asTelegramMedia()
|
||||
|
@ -30,21 +30,22 @@ data class VideoContent(
|
||||
replyParameters: ReplyParameters?,
|
||||
replyMarkup: KeyboardMarkup?
|
||||
): Request<ContentMessage<VideoContent>> = SendVideo(
|
||||
chatId,
|
||||
media.fileId,
|
||||
media.thumbnail ?.fileId,
|
||||
textSources,
|
||||
spoilered,
|
||||
media.duration,
|
||||
media.width,
|
||||
media.height,
|
||||
null,
|
||||
messageThreadId,
|
||||
businessConnectionId,
|
||||
disableNotification,
|
||||
protectContent,
|
||||
replyParameters,
|
||||
replyMarkup
|
||||
chatId = chatId,
|
||||
video = media.fileId,
|
||||
thumbnail = media.thumbnail ?.fileId,
|
||||
entities = textSources,
|
||||
showCaptionAboveMedia = showCaptionAboveMedia,
|
||||
spoilered = spoilered,
|
||||
duration = media.duration,
|
||||
width = media.width,
|
||||
height = media.height,
|
||||
supportStreaming = null,
|
||||
threadId = messageThreadId,
|
||||
businessConnectionId = businessConnectionId,
|
||||
disableNotification = disableNotification,
|
||||
protectContent = protectContent,
|
||||
replyParameters = replyParameters,
|
||||
replyMarkup = replyMarkup
|
||||
)
|
||||
|
||||
override fun toMediaGroupMemberTelegramMedia(): TelegramMediaVideo = asTelegramMedia()
|
||||
|
@ -0,0 +1,26 @@
|
||||
package dev.inmo.tgbotapi.types.message.textsources
|
||||
|
||||
import dev.inmo.tgbotapi.utils.RiskFeature
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.utils.internal.*
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* @see expandableBlockquote
|
||||
*/
|
||||
@Serializable
|
||||
data class ExpandableBlockquoteTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
||||
override val source: String,
|
||||
override val subsources: TextSourcesList
|
||||
) : MultilevelTextSource {
|
||||
override val markdown: String by lazy { source.expandableBlockquoteMarkdown() }
|
||||
override val markdownV2: String by lazy { expandableBlockquoteMarkdownV2() }
|
||||
override val html: String by lazy { expandableBlockquoteHTML() }
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun expandableBlockquote(parts: TextSourcesList) = ExpandableBlockquoteTextSource(parts.makeString(), parts)
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun expandableBlockquote(vararg parts: TextSource) = expandableBlockquote(parts.toList())
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun expandableBlockquote(text: String) = expandableBlockquote(regular(text))
|
@ -22,14 +22,37 @@ sealed interface TextSource {
|
||||
get() = source
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline operator fun TextSource.plus(other: TextSource) = listOf(this, other)
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline operator fun TextSource.plus(other: List<TextSource>) = listOf(this) + other
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline operator fun TextSource.plus(text: String) = listOf(this, regular(text))
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline operator fun List<TextSource>.plus(text: String) = this + regular(text)
|
||||
operator fun TextSource.plus(other: TextSource) = when {
|
||||
this is RegularTextSource && other is RegularTextSource -> listOf(RegularTextSource(source + other.source))
|
||||
else -> listOf(this, other)
|
||||
}
|
||||
operator fun TextSource.plus(text: String) = this + regular(text)
|
||||
operator fun List<TextSource>.plus(text: String): List<TextSource> {
|
||||
val newList = mutableListOf<TextSource>()
|
||||
|
||||
for (i in 0 until size - 1) {
|
||||
newList.add(get(i))
|
||||
}
|
||||
|
||||
val sublist = lastOrNull() ?.let {
|
||||
it + text
|
||||
} ?: listOf(regular(text))
|
||||
|
||||
newList.addAll(sublist)
|
||||
|
||||
return newList
|
||||
}
|
||||
operator fun TextSource.plus(other: List<TextSource>) = other.fold(listOf(this)) { acc, textSource ->
|
||||
val newList = mutableListOf<TextSource>()
|
||||
|
||||
for (i in 0 until acc.size - 1) {
|
||||
newList.add(acc.get(i))
|
||||
}
|
||||
|
||||
newList.addAll(acc.last() + textSource)
|
||||
|
||||
newList
|
||||
}
|
||||
|
||||
@Serializable(TextSourceSerializer::class)
|
||||
sealed interface MultilevelTextSource : TextSource {
|
||||
|
@ -140,6 +140,44 @@ inline fun EntitiesBuilder.blockquote(text: String) = add(dev.inmo.tgbotapi.type
|
||||
*/
|
||||
inline fun EntitiesBuilder.blockquoteln(text: String) = blockquote(text) + newLine
|
||||
|
||||
|
||||
/**
|
||||
* Add blockquote using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.message.textsources.blockquote]
|
||||
*/
|
||||
inline fun EntitiesBuilder.expandableBlockquote(parts: TextSourcesList) = add(dev.inmo.tgbotapi.types.message.textsources.expandableBlockquote(parts))
|
||||
/**
|
||||
* Version of [EntitiesBuilder.expandableBlockquote] with new line at the end
|
||||
*/
|
||||
inline fun EntitiesBuilder.expandableBlockquoteln(parts: TextSourcesList) = expandableBlockquote(parts) + newLine
|
||||
/**
|
||||
* Add expandableBlockquote using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.message.textsources.expandableBlockquote].
|
||||
* Will reuse separator config from [buildEntities]
|
||||
*/
|
||||
inline fun EntitiesBuilder.expandableBlockquote(noinline init: EntitiesBuilderBody) = add(dev.inmo.tgbotapi.types.message.textsources.expandableBlockquote(
|
||||
buildEntities(separator, init)
|
||||
))
|
||||
/**
|
||||
* Version of [EntitiesBuilder.expandableBlockquote] with new line at the end.
|
||||
* Will reuse separator config from [buildEntities]
|
||||
*/
|
||||
inline fun EntitiesBuilder.expandableBlockquoteln(noinline init: EntitiesBuilderBody) = expandableBlockquote(init) + newLine
|
||||
/**
|
||||
* Add expandableBlockquote using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.message.textsources.expandableBlockquote]
|
||||
*/
|
||||
inline fun EntitiesBuilder.expandableBlockquote(vararg parts: TextSource) = add(dev.inmo.tgbotapi.types.message.textsources.expandableBlockquote(*parts))
|
||||
/**
|
||||
* Version of [EntitiesBuilder.expandableBlockquote] with new line at the end
|
||||
*/
|
||||
inline fun EntitiesBuilder.expandableBlockquoteln(vararg parts: TextSource) = expandableBlockquote(*parts) + newLine
|
||||
/**
|
||||
* Add expandableBlockquote using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.message.textsources.expandableBlockquote]
|
||||
*/
|
||||
inline fun EntitiesBuilder.expandableBlockquote(text: String) = add(dev.inmo.tgbotapi.types.message.textsources.expandableBlockquote(text))
|
||||
/**
|
||||
* Version of [EntitiesBuilder.expandableBlockquote] with new line at the end
|
||||
*/
|
||||
inline fun EntitiesBuilder.expandableBlockquoteln(text: String) = expandableBlockquote(text) + newLine
|
||||
|
||||
/**
|
||||
* Add spoiler using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.message.textsources.spoiler]
|
||||
*/
|
||||
|
@ -45,6 +45,17 @@ internal fun MultilevelTextSource.blockquoteMarkdownV2(): String = markdownV2Def
|
||||
internal fun MultilevelTextSource.blockquoteHTML(): String = htmlDefault(htmlBlockquoteControl)
|
||||
|
||||
|
||||
internal fun MultilevelTextSource.expandableBlockquoteMarkdownV2(): String = markdownV2Default(
|
||||
openControlSymbol = markdownV2ExpandableBlockquoteOpenControl,
|
||||
closeControlSymbol = markdownV2ExpandableBlockquoteCloseControl,
|
||||
eachLineSeparator = markdownBlockquoteControl
|
||||
)
|
||||
internal fun MultilevelTextSource.expandableBlockquoteHTML(): String = htmlDefault(
|
||||
openControlSymbol = htmlBlockquoteOpenControl,
|
||||
closeControlSymbol = htmlBlockquoteControl
|
||||
)
|
||||
|
||||
|
||||
internal fun MultilevelTextSource.cashTagMarkdownV2(): String = subsources.makeMarkdownV2String()
|
||||
internal fun MultilevelTextSource.cashTagHTML(): String = subsources.makeHtmlString()
|
||||
|
||||
|
@ -16,9 +16,12 @@ const val markdownV2StrikethroughControl = "~"
|
||||
const val markdownV2UnderlineControl = "__"
|
||||
const val markdownV2UnderlineEndControl = "$markdownV2UnderlineControl$markdownV2ItalicUnderlineDelimiter"
|
||||
const val markdownV2ItalicEndControl = "$markdownItalicControl$markdownV2ItalicUnderlineDelimiter"
|
||||
const val markdownV2ExpandableBlockquoteOpenControl = "**"
|
||||
const val markdownV2ExpandableBlockquoteCloseControl = "||"
|
||||
|
||||
const val htmlBoldControl = "b"
|
||||
const val htmlBlockquoteControl = "blockquote"
|
||||
const val htmlBlockquoteOpenControl = "blockquote expandable"
|
||||
const val htmlItalicControl = "i"
|
||||
const val htmlSpoilerControl = "span class=\"tg-spoiler\""
|
||||
const val htmlSpoilerClosingControl = "span"
|
||||
@ -51,6 +54,8 @@ internal fun String.boldMarkdown(): String = markdownDefault(markdownBoldControl
|
||||
|
||||
internal fun String.blockquoteMarkdown(): String = regularMarkdown()
|
||||
|
||||
internal fun String.expandableBlockquoteMarkdown(): String = regularMarkdown()
|
||||
|
||||
internal fun String.italicMarkdown(): String = markdownDefault(markdownItalicControl)
|
||||
|
||||
internal fun String.spoilerMarkdown(): String = regularMarkdown()
|
||||
|
@ -1,14 +1,21 @@
|
||||
package dev.inmo.tgbotapi.types.MessageEntity
|
||||
|
||||
import dev.inmo.tgbotapi.types.message.RawMessageEntity
|
||||
import dev.inmo.tgbotapi.types.message.asTextSources
|
||||
import dev.inmo.tgbotapi.types.message.textsources.*
|
||||
import dev.inmo.tgbotapi.types.message.toRawMessageEntities
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeSourceString
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
const val testText = "It (is?) is simple hello world with #tag and @mention. Start of blockquote: Block quotation started\n" +
|
||||
"Block quotation continued\n" +
|
||||
"The last line of the block quotation\n" +
|
||||
". Start of expandable blockquote: Block quotation started\n" +
|
||||
"Block quotation continued\n" +
|
||||
"The last line of the block quotation"
|
||||
const val formattedV2Text = "It \\(is?\\) *_is_ ~__simple__~* ||hello world|| with \\#tag and @mention\\. Start of blockquote: >Block quotation started\n>Block quotation continued\n>The last line of the block quotation"
|
||||
const val formattedHtmlText = "It (is?) <b><i>is</i> <s><u>simple</u></s></b> <span class=\"tg-spoiler\">hello world</span> with #tag and @mention. Start of blockquote: <blockquote>Block quotation started\nBlock quotation continued\nThe last line of the block quotation</blockquote>"
|
||||
const val formattedV2Text = "It \\(is?\\) *_is_ ~__simple__~* ||hello world|| with \\#tag and @mention\\. Start of blockquote: >Block quotation started\n>Block quotation continued\n>The last line of the block quotation\n\\. Start of expandable blockquote: **>Block quotation started\n>Block quotation continued\n>The last line of the block quotation||"
|
||||
const val formattedHtmlText = "It (is?) <b><i>is</i> <s><u>simple</u></s></b> <span class=\"tg-spoiler\">hello world</span> with #tag and @mention. Start of blockquote: <blockquote>Block quotation started\nBlock quotation continued\nThe last line of the block quotation</blockquote>\n. Start of expandable blockquote: <blockquote expandable>Block quotation started\nBlock quotation continued\nThe last line of the block quotation</blockquote>"
|
||||
internal val testTextEntities = listOf(
|
||||
RawMessageEntity(
|
||||
"bold",
|
||||
@ -49,6 +56,11 @@ internal val testTextEntities = listOf(
|
||||
"blockquote",
|
||||
76,
|
||||
86
|
||||
),
|
||||
RawMessageEntity(
|
||||
"expandable_blockquote",
|
||||
120,
|
||||
204
|
||||
)
|
||||
)
|
||||
|
||||
@ -72,4 +84,6 @@ fun TextSourcesList.testTextSources() {
|
||||
|
||||
val blockquoteSource = get(9) as BlockquoteTextSource
|
||||
assertTrue (blockquoteSource.subsources.first() is RegularTextSource)
|
||||
|
||||
assertEquals(this, toRawMessageEntities().asTextSources(makeSourceString()))
|
||||
}
|
||||
|
@ -54,6 +54,12 @@ class StringFormattingTests {
|
||||
"Block quotation started\n" +
|
||||
"Block quotation continued\n" +
|
||||
"The last line of the block quotation"
|
||||
) +
|
||||
"\n. Start of expandable blockquote: " +
|
||||
expandableBlockquote(
|
||||
"Block quotation started\n" +
|
||||
"Block quotation continued\n" +
|
||||
"The last line of the block quotation"
|
||||
)
|
||||
sources.testTextSources()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user