diff --git a/tgbotapi.core/api/tgbotapi.core.api b/tgbotapi.core/api/tgbotapi.core.api index 95e09872f0..e564b1c870 100644 --- a/tgbotapi.core/api/tgbotapi.core.api +++ b/tgbotapi.core/api/tgbotapi.core.api @@ -34473,6 +34473,8 @@ public final class dev/inmo/tgbotapi/types/rich/InputRichMessageKt { public abstract interface class dev/inmo/tgbotapi/types/rich/RichBlock { public static final field Companion Ldev/inmo/tgbotapi/types/rich/RichBlock$Companion; + public abstract fun getHtml ()Ljava/lang/String; + public abstract fun getMarkdown ()Ljava/lang/String; public abstract fun getType ()Ljava/lang/String; } @@ -34488,6 +34490,8 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlockAnchor : dev/inmo/tgbot public final fun copy (Ljava/lang/String;)Ldev/inmo/tgbotapi/types/rich/RichBlockAnchor; public static synthetic fun copy$default (Ldev/inmo/tgbotapi/types/rich/RichBlockAnchor;Ljava/lang/String;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/rich/RichBlockAnchor; public fun equals (Ljava/lang/Object;)Z + public fun getHtml ()Ljava/lang/String; + public fun getMarkdown ()Ljava/lang/String; public final fun getName ()Ljava/lang/String; public fun getType ()Ljava/lang/String; public fun hashCode ()I @@ -34523,6 +34527,8 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlockAnimation : dev/inmo/tg public final fun getAnimation ()Ldev/inmo/tgbotapi/types/files/AnimationFile; public final fun getCaption ()Ldev/inmo/tgbotapi/types/rich/RichBlockCaption; public final fun getHasSpoiler ()Ljava/lang/Boolean; + public fun getHtml ()Ljava/lang/String; + public fun getMarkdown ()Ljava/lang/String; public fun getType ()Ljava/lang/String; public fun hashCode ()I public fun toString ()Ljava/lang/String; @@ -34555,6 +34561,8 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlockAudio : dev/inmo/tgbota public fun equals (Ljava/lang/Object;)Z public final fun getAudio ()Ldev/inmo/tgbotapi/types/files/AudioFile; public final fun getCaption ()Ldev/inmo/tgbotapi/types/rich/RichBlockCaption; + public fun getHtml ()Ljava/lang/String; + public fun getMarkdown ()Ljava/lang/String; public fun getType ()Ljava/lang/String; public fun hashCode ()I public fun toString ()Ljava/lang/String; @@ -34587,6 +34595,8 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlockBlockQuotation : dev/in public fun equals (Ljava/lang/Object;)Z public final fun getBlocks ()Ljava/util/List; public final fun getCredit ()Ldev/inmo/tgbotapi/types/rich/RichText; + public fun getHtml ()Ljava/lang/String; + public fun getMarkdown ()Ljava/lang/String; public fun getType ()Ljava/lang/String; public fun hashCode ()I public fun toString ()Ljava/lang/String; @@ -34649,6 +34659,8 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlockCollage : dev/inmo/tgbo public fun equals (Ljava/lang/Object;)Z public final fun getBlocks ()Ljava/util/List; public final fun getCaption ()Ldev/inmo/tgbotapi/types/rich/RichBlockCaption; + public fun getHtml ()Ljava/lang/String; + public fun getMarkdown ()Ljava/lang/String; public fun getType ()Ljava/lang/String; public fun hashCode ()I public fun toString ()Ljava/lang/String; @@ -34681,6 +34693,8 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlockDetails : dev/inmo/tgbo public static synthetic fun copy$default (Ldev/inmo/tgbotapi/types/rich/RichBlockDetails;Ldev/inmo/tgbotapi/types/rich/RichText;Ljava/util/List;Ljava/lang/Boolean;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/rich/RichBlockDetails; public fun equals (Ljava/lang/Object;)Z public final fun getBlocks ()Ljava/util/List; + public fun getHtml ()Ljava/lang/String; + public fun getMarkdown ()Ljava/lang/String; public final fun getSummary ()Ldev/inmo/tgbotapi/types/rich/RichText; public fun getType ()Ljava/lang/String; public fun hashCode ()I @@ -34708,6 +34722,8 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlockDivider : dev/inmo/tgbo public static final field TYPE Ljava/lang/String; public fun ()V public fun equals (Ljava/lang/Object;)Z + public fun getHtml ()Ljava/lang/String; + public fun getMarkdown ()Ljava/lang/String; public fun getType ()Ljava/lang/String; public fun hashCode ()I public fun toString ()Ljava/lang/String; @@ -34736,6 +34752,8 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlockFooter : dev/inmo/tgbot public final fun copy (Ldev/inmo/tgbotapi/types/rich/RichText;)Ldev/inmo/tgbotapi/types/rich/RichBlockFooter; public static synthetic fun copy$default (Ldev/inmo/tgbotapi/types/rich/RichBlockFooter;Ldev/inmo/tgbotapi/types/rich/RichText;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/rich/RichBlockFooter; public fun equals (Ljava/lang/Object;)Z + public fun getHtml ()Ljava/lang/String; + public fun getMarkdown ()Ljava/lang/String; public final fun getText ()Ldev/inmo/tgbotapi/types/rich/RichText; public fun getType ()Ljava/lang/String; public fun hashCode ()I @@ -34758,9 +34776,7 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlockFooter$Companion { } public final class dev/inmo/tgbotapi/types/rich/RichBlockFormattingKt { - public static final fun getHtml (Ldev/inmo/tgbotapi/types/rich/RichBlock;)Ljava/lang/String; public static final fun getHtml (Ldev/inmo/tgbotapi/types/rich/RichTextInfo;)Ljava/lang/String; - public static final fun getMarkdown (Ldev/inmo/tgbotapi/types/rich/RichBlock;)Ljava/lang/String; public static final fun getMarkdown (Ldev/inmo/tgbotapi/types/rich/RichTextInfo;)Ljava/lang/String; public static final fun toRichHtml (Ljava/util/List;)Ljava/lang/String; public static final fun toRichMarkdown (Ljava/util/List;)Ljava/lang/String; @@ -34774,7 +34790,9 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlockList : dev/inmo/tgbotap public final fun copy (Ljava/util/List;)Ldev/inmo/tgbotapi/types/rich/RichBlockList; public static synthetic fun copy$default (Ldev/inmo/tgbotapi/types/rich/RichBlockList;Ljava/util/List;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/rich/RichBlockList; public fun equals (Ljava/lang/Object;)Z + public fun getHtml ()Ljava/lang/String; public final fun getItems ()Ljava/util/List; + public fun getMarkdown ()Ljava/lang/String; public fun getType ()Ljava/lang/String; public fun hashCode ()I public fun toString ()Ljava/lang/String; @@ -34856,7 +34874,9 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlockMap : dev/inmo/tgbotapi public fun equals (Ljava/lang/Object;)Z public final fun getCaption ()Ldev/inmo/tgbotapi/types/rich/RichBlockCaption; public final fun getHeight ()I + public fun getHtml ()Ljava/lang/String; public final fun getLocation ()Ldev/inmo/tgbotapi/types/location/StaticLocation; + public fun getMarkdown ()Ljava/lang/String; public fun getType ()Ljava/lang/String; public final fun getWidth ()I public final fun getZoom ()I @@ -34888,6 +34908,8 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlockMathematicalExpression public static synthetic fun copy$default (Ldev/inmo/tgbotapi/types/rich/RichBlockMathematicalExpression;Ljava/lang/String;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/rich/RichBlockMathematicalExpression; public fun equals (Ljava/lang/Object;)Z public final fun getExpression ()Ljava/lang/String; + public fun getHtml ()Ljava/lang/String; + public fun getMarkdown ()Ljava/lang/String; public fun getType ()Ljava/lang/String; public fun hashCode ()I public fun toString ()Ljava/lang/String; @@ -34916,6 +34938,8 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlockParagraph : dev/inmo/tg public final fun copy (Ldev/inmo/tgbotapi/types/rich/RichText;)Ldev/inmo/tgbotapi/types/rich/RichBlockParagraph; public static synthetic fun copy$default (Ldev/inmo/tgbotapi/types/rich/RichBlockParagraph;Ldev/inmo/tgbotapi/types/rich/RichText;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/rich/RichBlockParagraph; public fun equals (Ljava/lang/Object;)Z + public fun getHtml ()Ljava/lang/String; + public fun getMarkdown ()Ljava/lang/String; public final fun getText ()Ldev/inmo/tgbotapi/types/rich/RichText; public fun getType ()Ljava/lang/String; public fun hashCode ()I @@ -34950,6 +34974,8 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlockPhoto : dev/inmo/tgbota public fun equals (Ljava/lang/Object;)Z public final fun getCaption ()Ldev/inmo/tgbotapi/types/rich/RichBlockCaption; public final fun getHasSpoiler ()Ljava/lang/Boolean; + public fun getHtml ()Ljava/lang/String; + public fun getMarkdown ()Ljava/lang/String; public final fun getPhoto-bGlShw4 ()Ljava/util/List; public fun getType ()Ljava/lang/String; public fun hashCode ()I @@ -34981,7 +35007,9 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlockPreformatted : dev/inmo public final fun copy (Ldev/inmo/tgbotapi/types/rich/RichText;Ljava/lang/String;)Ldev/inmo/tgbotapi/types/rich/RichBlockPreformatted; public static synthetic fun copy$default (Ldev/inmo/tgbotapi/types/rich/RichBlockPreformatted;Ldev/inmo/tgbotapi/types/rich/RichText;Ljava/lang/String;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/rich/RichBlockPreformatted; public fun equals (Ljava/lang/Object;)Z + public fun getHtml ()Ljava/lang/String; public final fun getLanguage ()Ljava/lang/String; + public fun getMarkdown ()Ljava/lang/String; public final fun getText ()Ldev/inmo/tgbotapi/types/rich/RichText; public fun getType ()Ljava/lang/String; public fun hashCode ()I @@ -35014,6 +35042,8 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlockPullQuotation : dev/inm public static synthetic fun copy$default (Ldev/inmo/tgbotapi/types/rich/RichBlockPullQuotation;Ldev/inmo/tgbotapi/types/rich/RichText;Ldev/inmo/tgbotapi/types/rich/RichText;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/rich/RichBlockPullQuotation; public fun equals (Ljava/lang/Object;)Z public final fun getCredit ()Ldev/inmo/tgbotapi/types/rich/RichText; + public fun getHtml ()Ljava/lang/String; + public fun getMarkdown ()Ljava/lang/String; public final fun getText ()Ldev/inmo/tgbotapi/types/rich/RichText; public fun getType ()Ljava/lang/String; public fun hashCode ()I @@ -35044,6 +35074,8 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlockSectionHeading : dev/in public final fun copy (Ldev/inmo/tgbotapi/types/rich/RichText;I)Ldev/inmo/tgbotapi/types/rich/RichBlockSectionHeading; public static synthetic fun copy$default (Ldev/inmo/tgbotapi/types/rich/RichBlockSectionHeading;Ldev/inmo/tgbotapi/types/rich/RichText;IILjava/lang/Object;)Ldev/inmo/tgbotapi/types/rich/RichBlockSectionHeading; public fun equals (Ljava/lang/Object;)Z + public fun getHtml ()Ljava/lang/String; + public fun getMarkdown ()Ljava/lang/String; public final fun getSize ()I public final fun getText ()Ldev/inmo/tgbotapi/types/rich/RichText; public fun getType ()Ljava/lang/String; @@ -35082,6 +35114,8 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlockSlideshow : dev/inmo/tg public fun equals (Ljava/lang/Object;)Z public final fun getBlocks ()Ljava/util/List; public final fun getCaption ()Ldev/inmo/tgbotapi/types/rich/RichBlockCaption; + public fun getHtml ()Ljava/lang/String; + public fun getMarkdown ()Ljava/lang/String; public fun getType ()Ljava/lang/String; public fun hashCode ()I public fun toString ()Ljava/lang/String; @@ -35116,6 +35150,8 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlockTable : dev/inmo/tgbota public fun equals (Ljava/lang/Object;)Z public final fun getCaption ()Ldev/inmo/tgbotapi/types/rich/RichText; public final fun getCells ()Ljava/util/List; + public fun getHtml ()Ljava/lang/String; + public fun getMarkdown ()Ljava/lang/String; public fun getType ()Ljava/lang/String; public fun hashCode ()I public final fun isBordered ()Ljava/lang/Boolean; @@ -35184,6 +35220,8 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlockThinking : dev/inmo/tgb public final fun copy (Ldev/inmo/tgbotapi/types/rich/RichText;)Ldev/inmo/tgbotapi/types/rich/RichBlockThinking; public static synthetic fun copy$default (Ldev/inmo/tgbotapi/types/rich/RichBlockThinking;Ldev/inmo/tgbotapi/types/rich/RichText;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/rich/RichBlockThinking; public fun equals (Ljava/lang/Object;)Z + public fun getHtml ()Ljava/lang/String; + public fun getMarkdown ()Ljava/lang/String; public final fun getText ()Ldev/inmo/tgbotapi/types/rich/RichText; public fun getType ()Ljava/lang/String; public fun hashCode ()I @@ -35218,6 +35256,8 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlockVideo : dev/inmo/tgbota public fun equals (Ljava/lang/Object;)Z public final fun getCaption ()Ldev/inmo/tgbotapi/types/rich/RichBlockCaption; public final fun getHasSpoiler ()Ljava/lang/Boolean; + public fun getHtml ()Ljava/lang/String; + public fun getMarkdown ()Ljava/lang/String; public fun getType ()Ljava/lang/String; public final fun getVideo ()Ldev/inmo/tgbotapi/types/files/VideoFile; public fun hashCode ()I @@ -35250,6 +35290,8 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlockVoiceNote : dev/inmo/tg public static synthetic fun copy$default (Ldev/inmo/tgbotapi/types/rich/RichBlockVoiceNote;Ldev/inmo/tgbotapi/types/files/VoiceFile;Ldev/inmo/tgbotapi/types/rich/RichBlockCaption;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/rich/RichBlockVoiceNote; public fun equals (Ljava/lang/Object;)Z public final fun getCaption ()Ldev/inmo/tgbotapi/types/rich/RichBlockCaption; + public fun getHtml ()Ljava/lang/String; + public fun getMarkdown ()Ljava/lang/String; public fun getType ()Ljava/lang/String; public final fun getVoiceNote ()Ldev/inmo/tgbotapi/types/files/VoiceFile; public fun hashCode ()I @@ -35302,6 +35344,8 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlocksBuilder { public abstract interface class dev/inmo/tgbotapi/types/rich/RichText { public static final field Companion Ldev/inmo/tgbotapi/types/rich/RichText$Companion; + public abstract fun getHtml ()Ljava/lang/String; + public abstract fun getMarkdown ()Ljava/lang/String; } public final class dev/inmo/tgbotapi/types/rich/RichText$Companion { @@ -35716,8 +35760,6 @@ public final class dev/inmo/tgbotapi/types/rich/RichTextEntitySerializer : kotli public final class dev/inmo/tgbotapi/types/rich/RichTextFormattingKt { public static final fun escapeRichMarkdown (Ljava/lang/String;)Ljava/lang/String; - public static final fun getHtml (Ldev/inmo/tgbotapi/types/rich/RichText;)Ljava/lang/String; - public static final fun getMarkdown (Ldev/inmo/tgbotapi/types/rich/RichText;)Ljava/lang/String; public static final fun getSource (Ldev/inmo/tgbotapi/types/rich/RichText;)Ljava/lang/String; } @@ -35728,6 +35770,8 @@ public final class dev/inmo/tgbotapi/types/rich/RichTextGroup : dev/inmo/tgbotap public final fun copy (Ljava/util/List;)Ldev/inmo/tgbotapi/types/rich/RichTextGroup; public static synthetic fun copy$default (Ldev/inmo/tgbotapi/types/rich/RichTextGroup;Ljava/util/List;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/rich/RichTextGroup; public fun equals (Ljava/lang/Object;)Z + public fun getHtml ()Ljava/lang/String; + public fun getMarkdown ()Ljava/lang/String; public final fun getParts ()Ljava/util/List; public fun hashCode ()I public fun toString ()Ljava/lang/String; @@ -35977,6 +36021,8 @@ public final class dev/inmo/tgbotapi/types/rich/RichTextPlain : dev/inmo/tgbotap public final fun copy (Ljava/lang/String;)Ldev/inmo/tgbotapi/types/rich/RichTextPlain; public static synthetic fun copy$default (Ldev/inmo/tgbotapi/types/rich/RichTextPlain;Ljava/lang/String;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/rich/RichTextPlain; public fun equals (Ljava/lang/Object;)Z + public fun getHtml ()Ljava/lang/String; + public fun getMarkdown ()Ljava/lang/String; public final fun getText ()Ljava/lang/String; public fun hashCode ()I public fun toString ()Ljava/lang/String; diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichBlock.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichBlock.kt index 847003b0b2..6ab799ec33 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichBlock.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichBlock.kt @@ -18,6 +18,16 @@ import kotlinx.serialization.json.jsonPrimitive @ClassCastsIncluded sealed interface RichBlock { val type: String + + /** + * [Rich Markdown style](https://core.telegram.org/bots/api#rich-markdown-style) source of this single [RichBlock]. + */ + val markdown: String + + /** + * [Rich HTML style](https://core.telegram.org/bots/api#rich-html-style) source of this single [RichBlock]. + */ + val html: String } object RichBlockSerializer : JsonContentPolymorphicSerializer(RichBlock::class) { diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichBlockFormatting.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichBlockFormatting.kt index 2511d90d5f..cefa811de3 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichBlockFormatting.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichBlockFormatting.kt @@ -28,69 +28,13 @@ val RichTextInfo.markdown: String val RichTextInfo.html: String get() = blocks.toRichHtml() -/** - * [Rich Markdown style](https://core.telegram.org/bots/api#rich-markdown-style) source of this single [RichBlock]. - */ -val RichBlock.markdown: String - get() = when (this) { - is RichBlockParagraph -> text.markdown - is RichBlockSectionHeading -> "#".repeat(size) + " " + text.markdown - is RichBlockPreformatted -> "```" + (language ?: "") + "\n" + text.source + "\n```" - is RichBlockFooter -> "
${text.markdown}
" - is RichBlockDivider -> "---" - is RichBlockMathematicalExpression -> "\$\$" + expression + "\$\$" - is RichBlockAnchor -> "" - is RichBlockList -> richBlockListMarkdown(this) - is RichBlockBlockQuotation -> richBlockQuotationMarkdown(blocks, credit) - is RichBlockPullQuotation -> "" - is RichBlockCollage -> richMediaContainerMarkdown("tg-collage", blocks, caption) - is RichBlockSlideshow -> richMediaContainerMarkdown("tg-slideshow", blocks, caption) - is RichBlockTable -> richBlockTableMarkdown(this) - is RichBlockDetails -> "${summary.markdown}\n\n${blocks.toRichMarkdown()}\n\n" - is RichBlockMap -> richBlockMapMarkdown(this) - is RichBlockAnimation -> richMediaMarkdown(animation.fileId.fileId, caption) - is RichBlockAudio -> richMediaMarkdown(audio.fileId.fileId, caption) - is RichBlockPhoto -> richMediaMarkdown(photo.fileId.fileId, caption) - is RichBlockVideo -> richMediaMarkdown(video.fileId.fileId, caption) - is RichBlockVoiceNote -> richMediaMarkdown(voiceNote.fileId.fileId, caption) - is RichBlockThinking -> "${text.markdown}" - } +internal fun richOpenAttribute(isOpen: Boolean?): String = if (isOpen == true) " open" else "" -/** - * [Rich HTML style](https://core.telegram.org/bots/api#rich-html-style) source of this single [RichBlock]. - */ -val RichBlock.html: String - get() = when (this) { - is RichBlockParagraph -> "

${text.html}

" - is RichBlockSectionHeading -> "${text.html}" - is RichBlockPreformatted -> language?.let { "
${text.html}
" } ?: "
${text.html}
" - is RichBlockFooter -> "
${text.html}
" - is RichBlockDivider -> "
" - is RichBlockMathematicalExpression -> "$expression" - is RichBlockAnchor -> "" - is RichBlockList -> richBlockListHtml(this) - is RichBlockBlockQuotation -> "
${blocks.toRichHtml()}${creditCiteHtml(credit)}
" - is RichBlockPullQuotation -> "" - is RichBlockCollage -> richMediaContainerHtml("tg-collage", blocks, caption) - is RichBlockSlideshow -> richMediaContainerHtml("tg-slideshow", blocks, caption) - is RichBlockTable -> richBlockTableHtml(this) - is RichBlockDetails -> "${summary.html}${blocks.toRichHtml()}" - is RichBlockMap -> richBlockMapHtml(this) - is RichBlockAnimation -> richMediaHtml("video", animation.fileId.fileId, hasSpoiler == true, selfClosing = false, caption = caption) - is RichBlockAudio -> richMediaHtml("audio", audio.fileId.fileId, spoiler = false, selfClosing = false, caption = caption) - is RichBlockPhoto -> richMediaHtml("img", photo.fileId.fileId, hasSpoiler == true, selfClosing = true, caption = caption) - is RichBlockVideo -> richMediaHtml("video", video.fileId.fileId, hasSpoiler == true, selfClosing = false, caption = caption) - is RichBlockVoiceNote -> richMediaHtml("audio", voiceNote.fileId.fileId, spoiler = false, selfClosing = false, caption = caption) - is RichBlockThinking -> "${text.html}" - } +internal fun creditCiteMarkdown(credit: RichText?): String = credit?.let { "${it.markdown}" } ?: "" -private fun richOpenAttribute(isOpen: Boolean?): String = if (isOpen == true) " open" else "" +internal fun creditCiteHtml(credit: RichText?): String = credit?.let { "${it.html}" } ?: "" -private fun creditCiteMarkdown(credit: RichText?): String = credit?.let { "${it.markdown}" } ?: "" - -private fun creditCiteHtml(credit: RichText?): String = credit?.let { "${it.html}" } ?: "" - -private fun richBlockListMarkdown(list: RichBlockList): String = +internal fun richBlockListMarkdown(list: RichBlockList): String = list.items.mapIndexed { index, item -> val marker = when { item.hasCheckbox == true -> if (item.isChecked == true) "- [x] " else "- [ ] " @@ -102,7 +46,7 @@ private fun richBlockListMarkdown(list: RichBlockList): String = }.joinToString(separator = "\n") }.joinToString(separator = "\n") -private fun richBlockListHtml(list: RichBlockList): String { +internal fun richBlockListHtml(list: RichBlockList): String { val ordered = list.items.any { it.labelType != null } val tag = if (ordered) "ol" else "ul" val items = list.items.joinToString(separator = "") { item -> @@ -120,45 +64,45 @@ private fun richBlockListHtml(list: RichBlockList): String { return "<$tag>$items" } -private fun richBlockQuotationMarkdown(blocks: List, credit: RichText?): String { +internal fun richBlockQuotationMarkdown(blocks: List, credit: RichText?): String { val quoted = blocks.toRichMarkdown().lineSequence().joinToString(separator = "\n") { line -> if (line.isEmpty()) ">" else "> $line" } return quoted + (credit?.let { "\n> ${creditCiteMarkdown(it)}" } ?: "") } -private fun richMediaContainerMarkdown(tag: String, blocks: List, caption: RichBlockCaption?): String { +internal fun richMediaContainerMarkdown(tag: String, blocks: List, caption: RichBlockCaption?): String { val media = blocks.joinToString(separator = "\n") { it.markdown } val captionPart = caption?.let { "\n
${it.text.markdown}${creditCiteMarkdown(it.credit)}
" } ?: "" return "<$tag>\n\n$media$captionPart\n\n" } -private fun richMediaContainerHtml(tag: String, blocks: List, caption: RichBlockCaption?): String { +internal fun richMediaContainerHtml(tag: String, blocks: List, caption: RichBlockCaption?): String { val media = blocks.joinToString(separator = "") { it.html } val captionPart = caption?.let { "
${it.text.html}${creditCiteHtml(it.credit)}
" } ?: "" return "<$tag>$media$captionPart" } -private fun richMediaMarkdown(source: String, caption: RichBlockCaption?): String = +internal fun richMediaMarkdown(source: String, caption: RichBlockCaption?): String = caption?.let { "![](" + source + " \"" + it.text.source + "\")" } ?: "![]($source)" -private fun richMediaHtml(tag: String, source: String, spoiler: Boolean, selfClosing: Boolean, caption: RichBlockCaption?): String { +internal fun richMediaHtml(tag: String, source: String, spoiler: Boolean, selfClosing: Boolean, caption: RichBlockCaption?): String { val spoilerAttribute = if (spoiler) " tg-spoiler" else "" val element = if (selfClosing) "<$tag src=\"$source\"$spoilerAttribute/>" else "<$tag src=\"$source\"$spoilerAttribute>" return caption?.let { "
$element
${it.text.html}${creditCiteHtml(it.credit)}
" } ?: element } -private fun richBlockMapMarkdown(map: RichBlockMap): String { +internal fun richBlockMapMarkdown(map: RichBlockMap): String { val element = "" return map.caption?.let { "
$element
${it.text.markdown}${creditCiteMarkdown(it.credit)}
" } ?: element } -private fun richBlockMapHtml(map: RichBlockMap): String { +internal fun richBlockMapHtml(map: RichBlockMap): String { val element = "" return map.caption?.let { "
$element
${it.text.html}${creditCiteHtml(it.credit)}
" } ?: element } -private fun richBlockTableMarkdown(table: RichBlockTable): String { +internal fun richBlockTableMarkdown(table: RichBlockTable): String { if (table.cells.isEmpty()) return "" fun renderRow(row: List): String = row.joinToString(separator = " | ", prefix = "| ", postfix = " |") { it.text?.markdown ?: "" } @@ -177,7 +121,7 @@ private fun richBlockTableMarkdown(table: RichBlockTable): String { return lines.joinToString(separator = "\n") } -private fun richBlockTableHtml(table: RichBlockTable): String { +internal fun richBlockTableHtml(table: RichBlockTable): String { val attributes = buildString { if (table.isBordered == true) append(" bordered") if (table.isStriped == true) append(" striped") diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichBlocks.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichBlocks.kt index ddf293aff2..adbd6189cb 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichBlocks.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichBlocks.kt @@ -49,6 +49,11 @@ data class RichBlockParagraph( @SerialName(typeField) override val type: String = TYPE + override val markdown: String + get() = text.markdown + override val html: String + get() = "

${text.html}

" + companion object { const val TYPE = "paragraph" } @@ -73,6 +78,11 @@ data class RichBlockSectionHeading( @SerialName(typeField) override val type: String = TYPE + override val markdown: String + get() = "#".repeat(size) + " " + text.markdown + override val html: String + get() = "${text.html}" + companion object { const val TYPE = "heading" } @@ -94,6 +104,11 @@ data class RichBlockPreformatted( @SerialName(typeField) override val type: String = TYPE + override val markdown: String + get() = "```" + (language ?: "") + "\n" + text.source + "\n```" + override val html: String + get() = language?.let { "
${text.html}
" } ?: "
${text.html}
" + companion object { const val TYPE = "pre" } @@ -113,6 +128,11 @@ data class RichBlockFooter( @SerialName(typeField) override val type: String = TYPE + override val markdown: String + get() = "
${text.markdown}
" + override val html: String + get() = "
${text.html}
" + companion object { const val TYPE = "footer" } @@ -129,6 +149,11 @@ class RichBlockDivider : RichBlock { @SerialName(typeField) override val type: String = TYPE + override val markdown: String + get() = "---" + override val html: String + get() = "
" + override fun equals(other: Any?): Boolean = other is RichBlockDivider override fun hashCode(): Int = TYPE.hashCode() @@ -154,6 +179,11 @@ data class RichBlockMathematicalExpression( @SerialName(typeField) override val type: String = TYPE + override val markdown: String + get() = "\$\$" + expression + "\$\$" + override val html: String + get() = "$expression" + companion object { const val TYPE = "mathematical_expression" } @@ -173,6 +203,11 @@ data class RichBlockAnchor( @SerialName(typeField) override val type: String = TYPE + override val markdown: String + get() = "" + override val html: String + get() = "" + companion object { const val TYPE = "anchor" } @@ -192,6 +227,11 @@ data class RichBlockList( @SerialName(typeField) override val type: String = TYPE + override val markdown: String + get() = richBlockListMarkdown(this) + override val html: String + get() = richBlockListHtml(this) + companion object { const val TYPE = "list" } @@ -213,6 +253,11 @@ data class RichBlockBlockQuotation( @SerialName(typeField) override val type: String = TYPE + override val markdown: String + get() = richBlockQuotationMarkdown(blocks, credit) + override val html: String + get() = "
${blocks.toRichHtml()}${creditCiteHtml(credit)}
" + companion object { const val TYPE = "blockquote" } @@ -234,6 +279,11 @@ data class RichBlockPullQuotation( @SerialName(typeField) override val type: String = TYPE + override val markdown: String + get() = "" + override val html: String + get() = "" + companion object { const val TYPE = "pullquote" } @@ -255,6 +305,11 @@ data class RichBlockCollage( @SerialName(typeField) override val type: String = TYPE + override val markdown: String + get() = richMediaContainerMarkdown("tg-collage", blocks, caption) + override val html: String + get() = richMediaContainerHtml("tg-collage", blocks, caption) + companion object { const val TYPE = "collage" } @@ -276,6 +331,11 @@ data class RichBlockSlideshow( @SerialName(typeField) override val type: String = TYPE + override val markdown: String + get() = richMediaContainerMarkdown("tg-slideshow", blocks, caption) + override val html: String + get() = richMediaContainerHtml("tg-slideshow", blocks, caption) + companion object { const val TYPE = "slideshow" } @@ -301,6 +361,11 @@ data class RichBlockTable( @SerialName(typeField) override val type: String = TYPE + override val markdown: String + get() = richBlockTableMarkdown(this) + override val html: String + get() = richBlockTableHtml(this) + companion object { const val TYPE = "table" } @@ -324,6 +389,11 @@ data class RichBlockDetails( @SerialName(typeField) override val type: String = TYPE + override val markdown: String + get() = "${summary.markdown}\n\n${blocks.toRichMarkdown()}\n\n" + override val html: String + get() = "${summary.html}${blocks.toRichHtml()}" + companion object { const val TYPE = "details" } @@ -354,6 +424,11 @@ data class RichBlockMap( @SerialName(typeField) override val type: String = TYPE + override val markdown: String + get() = richBlockMapMarkdown(this) + override val html: String + get() = richBlockMapHtml(this) + companion object { const val TYPE = "map" } @@ -377,6 +452,11 @@ data class RichBlockAnimation( @SerialName(typeField) override val type: String = TYPE + override val markdown: String + get() = richMediaMarkdown(animation.fileId.fileId, caption) + override val html: String + get() = richMediaHtml("video", animation.fileId.fileId, hasSpoiler == true, selfClosing = false, caption = caption) + companion object { const val TYPE = "animation" } @@ -398,6 +478,11 @@ data class RichBlockAudio( @SerialName(typeField) override val type: String = TYPE + override val markdown: String + get() = richMediaMarkdown(audio.fileId.fileId, caption) + override val html: String + get() = richMediaHtml("audio", audio.fileId.fileId, spoiler = false, selfClosing = false, caption = caption) + companion object { const val TYPE = "audio" } @@ -421,6 +506,11 @@ data class RichBlockPhoto( @SerialName(typeField) override val type: String = TYPE + override val markdown: String + get() = richMediaMarkdown(photo.fileId.fileId, caption) + override val html: String + get() = richMediaHtml("img", photo.fileId.fileId, hasSpoiler == true, selfClosing = true, caption = caption) + companion object { const val TYPE = "photo" } @@ -444,6 +534,11 @@ data class RichBlockVideo( @SerialName(typeField) override val type: String = TYPE + override val markdown: String + get() = richMediaMarkdown(video.fileId.fileId, caption) + override val html: String + get() = richMediaHtml("video", video.fileId.fileId, hasSpoiler == true, selfClosing = false, caption = caption) + companion object { const val TYPE = "video" } @@ -465,6 +560,11 @@ data class RichBlockVoiceNote( @SerialName(typeField) override val type: String = TYPE + override val markdown: String + get() = richMediaMarkdown(voiceNote.fileId.fileId, caption) + override val html: String + get() = richMediaHtml("audio", voiceNote.fileId.fileId, spoiler = false, selfClosing = false, caption = caption) + companion object { const val TYPE = "voice_note" } @@ -484,6 +584,11 @@ data class RichBlockThinking( @SerialName(typeField) override val type: String = TYPE + override val markdown: String + get() = "${text.markdown}" + override val html: String + get() = "${text.html}" + companion object { const val TYPE = "thinking" } diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichText.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichText.kt index f270d7dada..db75fb6ccb 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichText.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichText.kt @@ -1,6 +1,7 @@ package dev.inmo.tgbotapi.types.rich import dev.inmo.tgbotapi.types.typeField +import dev.inmo.tgbotapi.utils.extensions.toHtml import dev.inmo.tgbotapi.utils.internal.ClassCastsIncluded import kotlinx.serialization.DeserializationStrategy import kotlinx.serialization.KSerializer @@ -18,7 +19,17 @@ import kotlinx.serialization.json.* */ @Serializable(RichTextSerializer::class) @ClassCastsIncluded -sealed interface RichText +sealed interface RichText { + /** + * [Rich Markdown style](https://core.telegram.org/bots/api#rich-markdown-style) representation of this [RichText]. + */ + val markdown: String + + /** + * [Rich HTML style](https://core.telegram.org/bots/api#rich-html-style) representation of this [RichText]. + */ + val html: String +} /** * A plain (non-formatted) part of a [RichText]. Serialized as a bare JSON string. @@ -26,7 +37,12 @@ sealed interface RichText @Serializable data class RichTextPlain( val text: String -) : RichText +) : RichText { + override val markdown: String + get() = text.escapeRichMarkdown() + override val html: String + get() = text.toHtml() +} /** * A group of [RichText]s. Serialized as a JSON array. @@ -34,7 +50,12 @@ data class RichTextPlain( @Serializable data class RichTextGroup( val parts: List -) : RichText +) : RichText { + override val markdown: String + get() = parts.joinToString(separator = "") { it.markdown } + override val html: String + get() = parts.joinToString(separator = "") { it.html } +} /** * Any typed (formatted) part of a [RichText]. Serialized as a JSON object with the [type] discriminator. @@ -43,8 +64,8 @@ data class RichTextGroup( sealed interface RichTextEntity : RichText { val type: String - val markdown: String - val html: String + override val markdown: String + override val html: String } object RichTextSerializer : KSerializer { diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichTextFormatting.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichTextFormatting.kt index 69fbe2da81..3c031ecf50 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichTextFormatting.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichTextFormatting.kt @@ -1,8 +1,5 @@ package dev.inmo.tgbotapi.types.rich -import dev.inmo.tgbotapi.types.internalUserLinkBeginning -import dev.inmo.tgbotapi.utils.extensions.toHtml - /** * Characters which have a special meaning in the * [Rich Markdown style](https://core.telegram.org/bots/api#rich-markdown-style) and must be escaped with a backslash @@ -60,23 +57,3 @@ val RichText.source: String is RichTextReference -> text.source is RichTextReferenceLink -> text.source } - -/** - * [Rich Markdown style](https://core.telegram.org/bots/api#rich-markdown-style) representation of this [RichText]. - */ -val RichText.markdown: String - get() = when (this) { - is RichTextPlain -> text.escapeRichMarkdown() - is RichTextGroup -> parts.joinToString(separator = "") { it.markdown } - is RichTextEntity -> markdown - } - -/** - * [Rich HTML style](https://core.telegram.org/bots/api#rich-html-style) representation of this [RichText]. - */ -val RichText.html: String - get() = when (this) { - is RichTextPlain -> text.toHtml() - is RichTextGroup -> parts.joinToString(separator = "") { it.html } - is RichTextEntity -> html - }