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