mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2026-09-02 06:09:19 +00:00
Fix Bot API 10.3 rich message contracts
This commit is contained in:
@@ -223,7 +223,7 @@ data class InputRichBlockBlockQuotation(
|
||||
}
|
||||
}
|
||||
|
||||
/** A block quotation that is collapsed by default. */
|
||||
/** A block quotation that users can expand. */
|
||||
@Serializable
|
||||
data class InputRichBlockExpandableBlockQuotation(
|
||||
@SerialName(textField)
|
||||
|
||||
@@ -305,7 +305,7 @@ data class RichBlockBlockQuotation(
|
||||
}
|
||||
|
||||
/**
|
||||
* A block quotation that is collapsed by default.
|
||||
* A block quotation that users can expand.
|
||||
*
|
||||
* @see <a href="https://core.telegram.org/bots/api#richblockexpandableblockquotation">RichBlockExpandableBlockQuotation</a>
|
||||
*/
|
||||
@@ -326,9 +326,9 @@ data class RichBlockExpandableBlockQuotation(
|
||||
companion object {
|
||||
const val TYPE = "expandable_blockquote"
|
||||
fun markdown(text: RichText, credit: RichText?): String =
|
||||
"<blockquote collapsed>${text.markdown}${creditCiteMarkdown(credit)}</blockquote>"
|
||||
"<blockquote expandable>${text.html}${creditCiteHtml(credit)}</blockquote>"
|
||||
fun html(text: RichText, credit: RichText?): String =
|
||||
"<blockquote collapsed>${text.html}${creditCiteHtml(credit)}</blockquote>"
|
||||
"<blockquote expandable>${text.html}${creditCiteHtml(credit)}</blockquote>"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,9 @@ sealed interface RichMessageButton {
|
||||
val text: RichText
|
||||
val style: RichMessageButtonStyle?
|
||||
|
||||
/** Creates rich HTML or Markdown button markup containing [text]. */
|
||||
fun toRichMarkup(text: String): String
|
||||
|
||||
@Serializable
|
||||
data class Url(
|
||||
@SerialName(textField) override val text: RichText,
|
||||
@@ -39,6 +42,10 @@ sealed interface RichMessageButton {
|
||||
@SerialName(styleField) override val style: RichMessageButtonStyle? = null
|
||||
) : RichMessageButton {
|
||||
init { validateRichMessageButton(text, style) }
|
||||
override fun toRichMarkup(text: String): String = richMarkup(text, style) {
|
||||
attribute("type", "url")
|
||||
attribute("url", url)
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@@ -48,6 +55,10 @@ sealed interface RichMessageButton {
|
||||
@SerialName(styleField) override val style: RichMessageButtonStyle? = null
|
||||
) : RichMessageButton {
|
||||
init { validateRichMessageButton(text, style, allowLinkStyle = true) }
|
||||
override fun toRichMarkup(text: String): String = richMarkup(text, style) {
|
||||
attribute("type", "callback_data")
|
||||
attribute("data", callbackData)
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@@ -57,6 +68,10 @@ sealed interface RichMessageButton {
|
||||
@SerialName(styleField) override val style: RichMessageButtonStyle? = null
|
||||
) : RichMessageButton {
|
||||
init { validateRichMessageButton(text, style) }
|
||||
override fun toRichMarkup(text: String): String = richMarkup(text, style) {
|
||||
attribute("type", "web_app")
|
||||
attribute("url", webApp.url)
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@@ -69,6 +84,13 @@ sealed interface RichMessageButton {
|
||||
validateRichMessageButton(text, style)
|
||||
require(loginUrl.botUsername == null) { "Rich message login URL buttons do not support bot usernames" }
|
||||
}
|
||||
override fun toRichMarkup(text: String): String = richMarkup(text, style) {
|
||||
attribute("type", "login_url")
|
||||
attribute("url", loginUrl.url)
|
||||
loginUrl.forwardText?.let { attribute("forward-text", it) }
|
||||
loginUrl.botUsername?.let { attribute("bot-username", it) }
|
||||
if (loginUrl.requestWriteAccess == true) add("request-write-access")
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@@ -78,6 +100,10 @@ sealed interface RichMessageButton {
|
||||
@SerialName(styleField) override val style: RichMessageButtonStyle? = null
|
||||
) : RichMessageButton {
|
||||
init { validateRichMessageButton(text, style) }
|
||||
override fun toRichMarkup(text: String): String = richMarkup(text, style) {
|
||||
attribute("type", "switch_inline_query")
|
||||
attribute("query", switchInlineQuery)
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@@ -87,6 +113,10 @@ sealed interface RichMessageButton {
|
||||
@SerialName(styleField) override val style: RichMessageButtonStyle? = null
|
||||
) : RichMessageButton {
|
||||
init { validateRichMessageButton(text, style) }
|
||||
override fun toRichMarkup(text: String): String = richMarkup(text, style) {
|
||||
attribute("type", "switch_inline_query_current_chat")
|
||||
attribute("query", switchInlineQueryCurrentChat)
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@@ -96,6 +126,14 @@ sealed interface RichMessageButton {
|
||||
@SerialName(styleField) override val style: RichMessageButtonStyle? = null
|
||||
) : RichMessageButton {
|
||||
init { validateRichMessageButton(text, style) }
|
||||
override fun toRichMarkup(text: String): String = richMarkup(text, style) {
|
||||
attribute("type", "switch_inline_query_chosen_chat")
|
||||
switchInlineQueryChosenChat.query?.let { attribute("query", it) }
|
||||
if (switchInlineQueryChosenChat.allowUsers) add("allow-user-chats")
|
||||
if (switchInlineQueryChosenChat.allowBots) add("allow-bot-chats")
|
||||
if (switchInlineQueryChosenChat.allowGroups) add("allow-group-chats")
|
||||
if (switchInlineQueryChosenChat.allowChannels) add("allow-channel-chats")
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@@ -105,6 +143,10 @@ sealed interface RichMessageButton {
|
||||
@SerialName(styleField) override val style: RichMessageButtonStyle? = null
|
||||
) : RichMessageButton {
|
||||
init { validateRichMessageButton(text, style) }
|
||||
override fun toRichMarkup(text: String): String = richMarkup(text, style) {
|
||||
attribute("type", "copy_text")
|
||||
attribute("text", copyText.text)
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@@ -116,6 +158,10 @@ sealed interface RichMessageButton {
|
||||
@SerialName(disabledField)
|
||||
@kotlinx.serialization.EncodeDefault
|
||||
val disabled: DisabledButton = DisabledButton
|
||||
|
||||
override fun toRichMarkup(text: String): String = richMarkup(text, style) {
|
||||
attribute("type", "disabled")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +170,7 @@ private fun validateRichMessageButton(
|
||||
style: RichMessageButtonStyle?,
|
||||
allowLinkStyle: Boolean = false
|
||||
) {
|
||||
require(text.isValidRichMessageButtonText()) {
|
||||
require(text.isValidRichMessageButtonText) {
|
||||
"Rich message button text can contain only plain text, custom emoji and date-time entities"
|
||||
}
|
||||
require(allowLinkStyle || style != RichMessageButtonStyle.Link) {
|
||||
@@ -132,14 +178,6 @@ private fun validateRichMessageButton(
|
||||
}
|
||||
}
|
||||
|
||||
private fun RichText.isValidRichMessageButtonText(): Boolean = when (this) {
|
||||
is RichTextPlain -> true
|
||||
is RichTextCustomEmoji -> true
|
||||
is RichTextDateTime -> text.isValidRichMessageButtonText()
|
||||
is RichTextGroup -> parts.all { it.isValidRichMessageButtonText() }
|
||||
else -> false
|
||||
}
|
||||
|
||||
/** Closed set of styles supported by [RichMessageButton]. */
|
||||
@Serializable(RichMessageButtonStyle.Serializer::class)
|
||||
sealed interface RichMessageButtonStyle {
|
||||
@@ -234,57 +272,21 @@ sealed interface RichBlockButtonAlignment {
|
||||
}
|
||||
}
|
||||
|
||||
internal fun RichMessageButton.toRichMarkup(text: String): String {
|
||||
private fun richMarkup(
|
||||
text: String,
|
||||
style: RichMessageButtonStyle?,
|
||||
buildAttributes: MutableList<String>.() -> Unit
|
||||
): String {
|
||||
val attributes = mutableListOf<String>()
|
||||
fun attribute(name: String, value: String) {
|
||||
attributes.add("$name=\"${value.escapeRichMarkupAttribute()}\"")
|
||||
}
|
||||
when (this) {
|
||||
is RichMessageButton.Url -> {
|
||||
attribute("type", "url")
|
||||
attribute("url", url)
|
||||
}
|
||||
is RichMessageButton.CallbackData -> {
|
||||
attribute("type", "callback_data")
|
||||
attribute("data", callbackData)
|
||||
}
|
||||
is RichMessageButton.WebApp -> {
|
||||
attribute("type", "web_app")
|
||||
attribute("url", webApp.url)
|
||||
}
|
||||
is RichMessageButton.LoginUrl -> {
|
||||
attribute("type", "login_url")
|
||||
attribute("url", loginUrl.url)
|
||||
loginUrl.forwardText?.let { attribute("forward-text", it) }
|
||||
loginUrl.botUsername?.let { attribute("bot-username", it) }
|
||||
if (loginUrl.requestWriteAccess == true) attributes.add("request-write-access")
|
||||
}
|
||||
is RichMessageButton.SwitchInlineQuery -> {
|
||||
attribute("type", "switch_inline_query")
|
||||
attribute("query", switchInlineQuery)
|
||||
}
|
||||
is RichMessageButton.SwitchInlineQueryCurrentChat -> {
|
||||
attribute("type", "switch_inline_query_current_chat")
|
||||
attribute("query", switchInlineQueryCurrentChat)
|
||||
}
|
||||
is RichMessageButton.SwitchInlineQueryChosenChat -> {
|
||||
attribute("type", "switch_inline_query_chosen_chat")
|
||||
switchInlineQueryChosenChat.query?.let { attribute("query", it) }
|
||||
if (switchInlineQueryChosenChat.allowUsers) attributes.add("allow-user-chats")
|
||||
if (switchInlineQueryChosenChat.allowBots) attributes.add("allow-bot-chats")
|
||||
if (switchInlineQueryChosenChat.allowGroups) attributes.add("allow-group-chats")
|
||||
if (switchInlineQueryChosenChat.allowChannels) attributes.add("allow-channel-chats")
|
||||
}
|
||||
is RichMessageButton.CopyText -> {
|
||||
attribute("type", "copy_text")
|
||||
attribute("text", copyText.text)
|
||||
}
|
||||
is RichMessageButton.Disabled -> attribute("type", "disabled")
|
||||
}
|
||||
style?.let { attribute("style", it.name) }
|
||||
attributes.buildAttributes()
|
||||
style?.let { attributes.attribute("style", it.name) }
|
||||
return "<tg-button ${attributes.joinToString(" ")}>$text</tg-button>"
|
||||
}
|
||||
|
||||
private fun MutableList<String>.attribute(name: String, value: String) {
|
||||
add("$name=\"${value.escapeRichMarkupAttribute()}\"")
|
||||
}
|
||||
|
||||
private fun String.escapeRichMarkupAttribute(): String = replace("&", "&")
|
||||
.replace("\"", """)
|
||||
.replace("<", "<")
|
||||
|
||||
@@ -36,6 +36,9 @@ sealed interface RichText {
|
||||
* [Rich HTML style](https://core.telegram.org/bots/api#rich-html-style) representation of this [RichText].
|
||||
*/
|
||||
val html: String
|
||||
|
||||
/** Whether this text is permitted as [RichMessageButton] text. */
|
||||
val isValidRichMessageButtonText: Boolean
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,6 +51,7 @@ data class RichTextPlain(
|
||||
override val rawText: String = text
|
||||
override val markdown: String = markdown(text)
|
||||
override val html: String = html(text)
|
||||
override val isValidRichMessageButtonText: Boolean = true
|
||||
|
||||
companion object {
|
||||
fun markdown(text: String): String = text.escapeRichMarkdown()
|
||||
@@ -65,6 +69,7 @@ data class RichTextGroup(
|
||||
override val rawText: String = parts.joinToString(separator = "") { it.rawText }
|
||||
override val markdown: String = markdown(parts)
|
||||
override val html: String = html(parts)
|
||||
override val isValidRichMessageButtonText: Boolean = parts.all { it.isValidRichMessageButtonText }
|
||||
|
||||
companion object {
|
||||
fun markdown(parts: List<RichText>): String = parts.joinToString(separator = "") { it.markdown }
|
||||
@@ -81,6 +86,7 @@ sealed interface RichTextEntity : RichText {
|
||||
|
||||
override val markdown: String
|
||||
override val html: String
|
||||
override val isValidRichMessageButtonText: Boolean
|
||||
}
|
||||
|
||||
object RichTextSerializer : KSerializer<RichText> {
|
||||
|
||||
@@ -46,6 +46,7 @@ data class RichTextButton(
|
||||
override val rawText: String = button.text.rawText
|
||||
override val markdown: String = markdown(button)
|
||||
override val html: String = html(button)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "button"
|
||||
@@ -71,6 +72,7 @@ data class RichTextBold(
|
||||
override val rawText: String = text.rawText
|
||||
override val markdown: String = markdown(text)
|
||||
override val html: String = html(text)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "bold"
|
||||
@@ -96,6 +98,7 @@ data class RichTextItalic(
|
||||
override val rawText: String = text.rawText
|
||||
override val markdown: String = markdown(text)
|
||||
override val html: String = html(text)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "italic"
|
||||
@@ -121,6 +124,7 @@ data class RichTextUnderline(
|
||||
override val rawText: String = text.rawText
|
||||
override val markdown: String = markdown(text)
|
||||
override val html: String = html(text)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "underline"
|
||||
@@ -146,6 +150,7 @@ data class RichTextStrikethrough(
|
||||
override val rawText: String = text.rawText
|
||||
override val markdown: String = markdown(text)
|
||||
override val html: String = html(text)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "strikethrough"
|
||||
@@ -171,6 +176,7 @@ data class RichTextSpoiler(
|
||||
override val rawText: String = text.rawText
|
||||
override val markdown: String = markdown(text)
|
||||
override val html: String = html(text)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "spoiler"
|
||||
@@ -196,6 +202,7 @@ data class RichTextSubscript(
|
||||
override val rawText: String = text.rawText
|
||||
override val markdown: String = markdown(text)
|
||||
override val html: String = html(text)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "subscript"
|
||||
@@ -221,6 +228,7 @@ data class RichTextSuperscript(
|
||||
override val rawText: String = text.rawText
|
||||
override val markdown: String = markdown(text)
|
||||
override val html: String = html(text)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "superscript"
|
||||
@@ -246,6 +254,7 @@ data class RichTextMarked(
|
||||
override val rawText: String = text.rawText
|
||||
override val markdown: String = markdown(text)
|
||||
override val html: String = html(text)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "marked"
|
||||
@@ -271,6 +280,7 @@ data class RichTextCode(
|
||||
override val rawText: String = text.rawText
|
||||
override val markdown: String = markdown(text)
|
||||
override val html: String = html(text)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "code"
|
||||
@@ -300,6 +310,7 @@ data class RichTextDateTime(
|
||||
override val rawText: String = text.rawText
|
||||
override val markdown: String = markdown(text, unixTime, dateTimeFormat)
|
||||
override val html: String = html(text, unixTime, dateTimeFormat)
|
||||
override val isValidRichMessageButtonText: Boolean = text.isValidRichMessageButtonText
|
||||
|
||||
companion object {
|
||||
const val TYPE = "date_time"
|
||||
@@ -329,6 +340,7 @@ data class RichTextTextMention(
|
||||
override val rawText: String = text.rawText
|
||||
override val markdown: String = markdown(text, user)
|
||||
override val html: String = html(text, user)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "text_mention"
|
||||
@@ -358,6 +370,7 @@ data class RichTextCustomEmoji(
|
||||
override val rawText: String = alternativeText
|
||||
override val markdown: String = markdown(customEmojiId, alternativeText)
|
||||
override val html: String = html(customEmojiId, alternativeText)
|
||||
override val isValidRichMessageButtonText: Boolean = true
|
||||
|
||||
companion object {
|
||||
const val TYPE = "custom_emoji"
|
||||
@@ -385,6 +398,7 @@ data class RichTextMathematicalExpression(
|
||||
override val rawText: String = expression
|
||||
override val markdown: String = markdown(expression)
|
||||
override val html: String = html(expression)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "mathematical_expression"
|
||||
@@ -412,6 +426,7 @@ data class RichTextUrl(
|
||||
override val rawText: String = text.rawText
|
||||
override val markdown: String = markdown(text, url)
|
||||
override val html: String = html(text, url)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "url"
|
||||
@@ -439,6 +454,7 @@ data class RichTextEmailAddress(
|
||||
override val rawText: String = text.rawText
|
||||
override val markdown: String = markdown(text, emailAddress)
|
||||
override val html: String = html(text, emailAddress)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "email_address"
|
||||
@@ -466,6 +482,7 @@ data class RichTextPhoneNumber(
|
||||
override val rawText: String = text.rawText
|
||||
override val markdown: String = markdown(text, phoneNumber)
|
||||
override val html: String = html(text, phoneNumber)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "phone_number"
|
||||
@@ -493,6 +510,7 @@ data class RichTextBankCardNumber(
|
||||
override val rawText: String = text.rawText
|
||||
override val markdown: String = markdown(text)
|
||||
override val html: String = html(text)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "bank_card_number"
|
||||
@@ -520,6 +538,7 @@ data class RichTextMention(
|
||||
override val rawText: String = text.rawText
|
||||
override val markdown: String = markdown(text)
|
||||
override val html: String = html(text)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "mention"
|
||||
@@ -547,6 +566,7 @@ data class RichTextHashtag(
|
||||
override val rawText: String = text.rawText
|
||||
override val markdown: String = markdown(text)
|
||||
override val html: String = html(text)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "hashtag"
|
||||
@@ -574,6 +594,7 @@ data class RichTextCashtag(
|
||||
override val rawText: String = text.rawText
|
||||
override val markdown: String = markdown(text)
|
||||
override val html: String = html(text)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "cashtag"
|
||||
@@ -601,6 +622,7 @@ data class RichTextBotCommand(
|
||||
override val rawText: String = text.rawText
|
||||
override val markdown: String = markdown(text)
|
||||
override val html: String = html(text)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "bot_command"
|
||||
@@ -626,6 +648,7 @@ data class RichTextAnchor(
|
||||
override val rawText: String = ""
|
||||
override val markdown: String = markdown(name)
|
||||
override val html: String = html(name)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "anchor"
|
||||
@@ -653,6 +676,7 @@ data class RichTextAnchorLink(
|
||||
override val rawText: String = text.rawText
|
||||
override val markdown: String = markdown(text, anchorName)
|
||||
override val html: String = html(text, anchorName)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "anchor_link"
|
||||
@@ -680,6 +704,7 @@ data class RichTextReference(
|
||||
override val rawText: String = text.rawText
|
||||
override val markdown: String = markdown(text, name)
|
||||
override val html: String = html(text, name)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "reference"
|
||||
@@ -707,6 +732,7 @@ data class RichTextReferenceLink(
|
||||
override val rawText: String = text.rawText
|
||||
override val markdown: String = markdown(text, referenceName)
|
||||
override val html: String = html(text, referenceName)
|
||||
override val isValidRichMessageButtonText: Boolean = false
|
||||
|
||||
companion object {
|
||||
const val TYPE = "reference_link"
|
||||
|
||||
@@ -114,6 +114,7 @@ class RichMessageSerializationTest {
|
||||
)
|
||||
|
||||
validTexts.forEach { text ->
|
||||
assertEquals(true, text.isValidRichMessageButtonText)
|
||||
assertEquals(text, RichMessageButton.Disabled(text).text)
|
||||
}
|
||||
|
||||
@@ -124,6 +125,7 @@ class RichMessageSerializationTest {
|
||||
RichTextDateTime(RichTextBold(plain), TelegramDate(1L), "wDT")
|
||||
)
|
||||
invalidTexts.forEach { text ->
|
||||
assertEquals(false, text.isValidRichMessageButtonText)
|
||||
assertFailsWith<IllegalArgumentException> { RichMessageButton.Disabled(text) }
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package dev.inmo.tgbotapi.types.rich
|
||||
|
||||
import dev.inmo.tgbotapi.types.CustomEmojiId
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
|
||||
class RichBlockFormattingTest {
|
||||
@Test
|
||||
@@ -99,8 +101,18 @@ class RichBlockFormattingTest {
|
||||
@Test
|
||||
fun expandableBlockQuotationAndButtons() {
|
||||
val quotation = RichBlockExpandableBlockQuotation(RichTextPlain("q"), RichTextPlain("credit"))
|
||||
assertEquals("<blockquote collapsed>q<cite>credit</cite></blockquote>", quotation.markdown)
|
||||
assertEquals("<blockquote collapsed>q<cite>credit</cite></blockquote>", quotation.html)
|
||||
assertEquals("<blockquote expandable>q<cite>credit</cite></blockquote>", quotation.markdown)
|
||||
assertEquals("<blockquote expandable>q<cite>credit</cite></blockquote>", quotation.html)
|
||||
val customEmojiQuotation = RichBlockExpandableBlockQuotation(
|
||||
RichTextCustomEmoji(CustomEmojiId("emoji"), "emoji"),
|
||||
RichTextCustomEmoji(CustomEmojiId("credit"), "credit")
|
||||
)
|
||||
assertEquals(
|
||||
"<blockquote expandable><tg-emoji emoji-id=\"emoji\">emoji</tg-emoji>" +
|
||||
"<cite><tg-emoji emoji-id=\"credit\">credit</tg-emoji></cite></blockquote>",
|
||||
customEmojiQuotation.markdown
|
||||
)
|
||||
assertFalse(customEmojiQuotation.markdown.contains("!["))
|
||||
val buttons = RichBlockButtons(listOf(RichMessageButton.Disabled(RichTextPlain("Disabled"))), RichBlockButtonAlignment.Right)
|
||||
assertEquals("<tg-button-row align=\"right\"><tg-button type=\"disabled\">Disabled</tg-button></tg-button-row>", buttons.html)
|
||||
}
|
||||
|
||||
@@ -245,7 +245,9 @@ class RichTextFormattingTest {
|
||||
SwitchInlineQueryChosenChatParameters(rawAttribute, allowUsers = true)
|
||||
) to "type=\"switch_inline_query_chosen_chat\" query=\"$escapedAttribute\" allow-user-chats",
|
||||
RichMessageButton.CopyText(text, CopyTextButtonData(rawAttribute)) to
|
||||
"type=\"copy_text\" text=\"$escapedAttribute\""
|
||||
"type=\"copy_text\" text=\"$escapedAttribute\"",
|
||||
RichMessageButton.Disabled(text) to
|
||||
"type=\"disabled\""
|
||||
)
|
||||
|
||||
buttonsWithExpectedAttributes.forEach { (button, expectedAttributes) ->
|
||||
|
||||
Reference in New Issue
Block a user