mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2024-11-25 19:48:43 +00:00
add blockquote
This commit is contained in:
parent
a01a9910b5
commit
db2101d85c
@ -22,24 +22,25 @@ internal data class RawMessageEntity(
|
|||||||
val priority by lazy {
|
val priority by lazy {
|
||||||
when (type) {
|
when (type) {
|
||||||
// Types with potential subsources should have priority
|
// Types with potential subsources should have priority
|
||||||
"mention" -> 0
|
"mention" -> 1
|
||||||
"hashtag" -> 0
|
"hashtag" -> 1
|
||||||
"cashtag" -> 0
|
"cashtag" -> 1
|
||||||
"email" -> 0
|
"email" -> 1
|
||||||
"phone_number" -> 0
|
"phone_number" -> 1
|
||||||
"bold" -> 0
|
"bold" -> 1
|
||||||
"italic" -> 0
|
"blockquote" -> 0
|
||||||
"text_mention" -> 0
|
"italic" -> 1
|
||||||
"strikethrough" -> 0
|
"text_mention" -> 1
|
||||||
"underline" -> 0
|
"strikethrough" -> 1
|
||||||
"spoiler" -> 0
|
"underline" -> 1
|
||||||
"custom_emoji" -> 0
|
"spoiler" -> 1
|
||||||
"bot_command" -> 1
|
"custom_emoji" -> 1
|
||||||
"url" -> 1
|
"bot_command" -> 2
|
||||||
"code" -> 1
|
"url" -> 2
|
||||||
"pre" -> 1
|
"code" -> 2
|
||||||
"text_link" -> 1
|
"pre" -> 2
|
||||||
else -> 1
|
"text_link" -> 2
|
||||||
|
else -> 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,6 +62,7 @@ internal fun RawMessageEntity.asTextSource(
|
|||||||
"email" -> EMailTextSource(sourceSubstring, subPartsWithRegulars)
|
"email" -> EMailTextSource(sourceSubstring, subPartsWithRegulars)
|
||||||
"phone_number" -> PhoneNumberTextSource(sourceSubstring, subPartsWithRegulars)
|
"phone_number" -> PhoneNumberTextSource(sourceSubstring, subPartsWithRegulars)
|
||||||
"bold" -> BoldTextSource(sourceSubstring, subPartsWithRegulars)
|
"bold" -> BoldTextSource(sourceSubstring, subPartsWithRegulars)
|
||||||
|
"blockquote" -> BlockquoteTextSource(sourceSubstring, subPartsWithRegulars)
|
||||||
"italic" -> ItalicTextSource(sourceSubstring, subPartsWithRegulars)
|
"italic" -> ItalicTextSource(sourceSubstring, subPartsWithRegulars)
|
||||||
"code" -> CodeTextSource(sourceSubstring)
|
"code" -> CodeTextSource(sourceSubstring)
|
||||||
"pre" -> PreTextSource(sourceSubstring, language)
|
"pre" -> PreTextSource(sourceSubstring, language)
|
||||||
@ -180,6 +182,7 @@ internal fun TextSource.toRawMessageEntities(offset: Int = 0): List<RawMessageEn
|
|||||||
is EMailTextSource -> RawMessageEntity("email", offset, length)
|
is EMailTextSource -> RawMessageEntity("email", offset, length)
|
||||||
is PhoneNumberTextSource -> RawMessageEntity("phone_number", offset, length)
|
is PhoneNumberTextSource -> RawMessageEntity("phone_number", offset, length)
|
||||||
is BoldTextSource -> RawMessageEntity("bold", offset, length)
|
is BoldTextSource -> RawMessageEntity("bold", offset, length)
|
||||||
|
is BlockquoteTextSource -> RawMessageEntity("blockquote", offset, length)
|
||||||
is ItalicTextSource -> RawMessageEntity("italic", offset, length)
|
is ItalicTextSource -> RawMessageEntity("italic", offset, length)
|
||||||
is CodeTextSource -> RawMessageEntity("code", offset, length)
|
is CodeTextSource -> RawMessageEntity("code", offset, length)
|
||||||
is PreTextSource -> RawMessageEntity("pre", offset, length, language = language)
|
is PreTextSource -> RawMessageEntity("pre", offset, length, language = language)
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
package dev.inmo.tgbotapi.types.message.textsources
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.utils.RiskFeature
|
||||||
|
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||||
|
import dev.inmo.tgbotapi.utils.internal.*
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see blockquote
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
data class BlockquoteTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
||||||
|
override val source: String,
|
||||||
|
override val subsources: TextSourcesList
|
||||||
|
) : MultilevelTextSource {
|
||||||
|
override val markdown: String by lazy { source.blockquoteMarkdown() }
|
||||||
|
override val markdownV2: String by lazy { blockquoteMarkdownV2() }
|
||||||
|
override val html: String by lazy { blockquoteHTML() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
inline fun blockquote(parts: TextSourcesList) = BlockquoteTextSource(parts.makeString(), parts)
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
inline fun blockquote(vararg parts: TextSource) = blockquote(parts.toList())
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
inline fun blockquote(text: String) = blockquote(regular(text))
|
@ -103,6 +103,43 @@ inline fun EntitiesBuilder.bold(text: String) = add(dev.inmo.tgbotapi.types.mess
|
|||||||
*/
|
*/
|
||||||
inline fun EntitiesBuilder.boldln(text: String) = bold(text) + newLine
|
inline fun EntitiesBuilder.boldln(text: String) = bold(text) + newLine
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add blockquote using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.message.textsources.blockquote]
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.blockquote(parts: TextSourcesList) = add(dev.inmo.tgbotapi.types.message.textsources.blockquote(parts))
|
||||||
|
/**
|
||||||
|
* Version of [EntitiesBuilder.blockquote] with new line at the end
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.blockquoteln(parts: TextSourcesList) = blockquote(parts) + newLine
|
||||||
|
/**
|
||||||
|
* Add blockquote using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.message.textsources.blockquote].
|
||||||
|
* Will reuse separator config from [buildEntities]
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.blockquote(noinline init: EntitiesBuilderBody) = add(dev.inmo.tgbotapi.types.message.textsources.blockquote(
|
||||||
|
buildEntities(separator, init)
|
||||||
|
))
|
||||||
|
/**
|
||||||
|
* Version of [EntitiesBuilder.blockquote] with new line at the end.
|
||||||
|
* Will reuse separator config from [buildEntities]
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.blockquoteln(noinline init: EntitiesBuilderBody) = blockquote(init) + newLine
|
||||||
|
/**
|
||||||
|
* Add blockquote using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.message.textsources.blockquote]
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.blockquote(vararg parts: TextSource) = add(dev.inmo.tgbotapi.types.message.textsources.blockquote(*parts))
|
||||||
|
/**
|
||||||
|
* Version of [EntitiesBuilder.blockquote] with new line at the end
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.blockquoteln(vararg parts: TextSource) = blockquote(*parts) + newLine
|
||||||
|
/**
|
||||||
|
* Add blockquote using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.message.textsources.blockquote]
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.blockquote(text: String) = add(dev.inmo.tgbotapi.types.message.textsources.blockquote(text))
|
||||||
|
/**
|
||||||
|
* Version of [EntitiesBuilder.blockquote] with new line at the end
|
||||||
|
*/
|
||||||
|
inline fun EntitiesBuilder.blockquoteln(text: String) = blockquote(text) + newLine
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add spoiler using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.message.textsources.spoiler]
|
* Add spoiler using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.message.textsources.spoiler]
|
||||||
*/
|
*/
|
||||||
|
@ -3,6 +3,8 @@ package dev.inmo.tgbotapi.utils.extensions
|
|||||||
import dev.inmo.tgbotapi.types.message.textsources.TextSourcesList
|
import dev.inmo.tgbotapi.types.message.textsources.TextSourcesList
|
||||||
import dev.inmo.tgbotapi.types.message.*
|
import dev.inmo.tgbotapi.types.message.*
|
||||||
|
|
||||||
|
val eachLineRegex = Regex("^[^\n]")
|
||||||
|
|
||||||
inline fun TextSourcesList.makeString(
|
inline fun TextSourcesList.makeString(
|
||||||
parseMode: ParseMode? = null
|
parseMode: ParseMode? = null
|
||||||
) = when (parseMode) {
|
) = when (parseMode) {
|
||||||
@ -21,8 +23,23 @@ inline fun TextSourcesList.makeHtmlString() = joinToString("") {
|
|||||||
it.html
|
it.html
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun TextSourcesList.makeMarkdownV2String() = joinToString("") {
|
inline fun TextSourcesList.makeMarkdownV2String(eachLineSeparator: String? = null) = joinToString("") {
|
||||||
it.markdownV2
|
it.markdownV2
|
||||||
|
}.let {
|
||||||
|
if (eachLineSeparator == null) {
|
||||||
|
it
|
||||||
|
} else {
|
||||||
|
it.let {
|
||||||
|
if (it.startsWith("\n")) {
|
||||||
|
it
|
||||||
|
} else {
|
||||||
|
"$eachLineSeparator$it"
|
||||||
|
}
|
||||||
|
}.replace(
|
||||||
|
"\n",
|
||||||
|
"\n$eachLineSeparator"
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun TextSourcesList.makeMarkdownString() = joinToString("") {
|
inline fun TextSourcesList.makeMarkdownString() = joinToString("") {
|
||||||
|
@ -6,8 +6,9 @@ import dev.inmo.tgbotapi.utils.extensions.*
|
|||||||
|
|
||||||
internal fun MultilevelTextSource.markdownV2Default(
|
internal fun MultilevelTextSource.markdownV2Default(
|
||||||
openControlSymbol: String,
|
openControlSymbol: String,
|
||||||
closeControlSymbol: String = openControlSymbol
|
closeControlSymbol: String = openControlSymbol,
|
||||||
) = "$openControlSymbol${subsources.makeMarkdownV2String()}$closeControlSymbol"
|
eachLineSeparator: String? = null
|
||||||
|
) = "$openControlSymbol${subsources.makeMarkdownV2String(eachLineSeparator)}$closeControlSymbol"
|
||||||
internal fun MultilevelTextSource.htmlDefault(
|
internal fun MultilevelTextSource.htmlDefault(
|
||||||
openControlSymbol: String,
|
openControlSymbol: String,
|
||||||
closeControlSymbol: String = openControlSymbol
|
closeControlSymbol: String = openControlSymbol
|
||||||
@ -40,6 +41,10 @@ internal fun MultilevelTextSource.boldMarkdownV2(): String = markdownV2Default(m
|
|||||||
internal fun MultilevelTextSource.boldHTML(): String = htmlDefault(htmlBoldControl)
|
internal fun MultilevelTextSource.boldHTML(): String = htmlDefault(htmlBoldControl)
|
||||||
|
|
||||||
|
|
||||||
|
internal fun MultilevelTextSource.blockquoteMarkdownV2(): String = markdownV2Default("", eachLineSeparator = markdownBlockquoteControl)
|
||||||
|
internal fun MultilevelTextSource.blockquoteHTML(): String = htmlDefault(htmlBlockquoteControl)
|
||||||
|
|
||||||
|
|
||||||
internal fun MultilevelTextSource.cashTagMarkdownV2(): String = subsources.makeMarkdownV2String()
|
internal fun MultilevelTextSource.cashTagMarkdownV2(): String = subsources.makeMarkdownV2String()
|
||||||
internal fun MultilevelTextSource.cashTagHTML(): String = subsources.makeHtmlString()
|
internal fun MultilevelTextSource.cashTagHTML(): String = subsources.makeHtmlString()
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import dev.inmo.tgbotapi.types.message.*
|
|||||||
import dev.inmo.tgbotapi.utils.extensions.*
|
import dev.inmo.tgbotapi.utils.extensions.*
|
||||||
|
|
||||||
const val markdownBoldControl = "*"
|
const val markdownBoldControl = "*"
|
||||||
|
const val markdownBlockquoteControl = ">"
|
||||||
const val markdownItalicControl = "_"
|
const val markdownItalicControl = "_"
|
||||||
const val markdownSpoilerControl = "||"
|
const val markdownSpoilerControl = "||"
|
||||||
const val markdownCodeControl = "`"
|
const val markdownCodeControl = "`"
|
||||||
@ -17,6 +18,7 @@ const val markdownV2UnderlineEndControl = "$markdownV2UnderlineControl$markdownV
|
|||||||
const val markdownV2ItalicEndControl = "$markdownItalicControl$markdownV2ItalicUnderlineDelimiter"
|
const val markdownV2ItalicEndControl = "$markdownItalicControl$markdownV2ItalicUnderlineDelimiter"
|
||||||
|
|
||||||
const val htmlBoldControl = "b"
|
const val htmlBoldControl = "b"
|
||||||
|
const val htmlBlockquoteControl = "blockquote"
|
||||||
const val htmlItalicControl = "i"
|
const val htmlItalicControl = "i"
|
||||||
const val htmlSpoilerControl = "span class=\"tg-spoiler\""
|
const val htmlSpoilerControl = "span class=\"tg-spoiler\""
|
||||||
const val htmlSpoilerClosingControl = "span"
|
const val htmlSpoilerClosingControl = "span"
|
||||||
@ -47,6 +49,8 @@ internal fun String.linkHTML(link: String): String = "<a href=\"$link\">${toHtml
|
|||||||
|
|
||||||
internal fun String.boldMarkdown(): String = markdownDefault(markdownBoldControl)
|
internal fun String.boldMarkdown(): String = markdownDefault(markdownBoldControl)
|
||||||
|
|
||||||
|
internal fun String.blockquoteMarkdown(): String = regularMarkdown()
|
||||||
|
|
||||||
internal fun String.italicMarkdown(): String = markdownDefault(markdownItalicControl)
|
internal fun String.italicMarkdown(): String = markdownDefault(markdownItalicControl)
|
||||||
|
|
||||||
internal fun String.spoilerMarkdown(): String = regularMarkdown()
|
internal fun String.spoilerMarkdown(): String = regularMarkdown()
|
||||||
|
@ -4,9 +4,11 @@ import dev.inmo.tgbotapi.types.message.RawMessageEntity
|
|||||||
import dev.inmo.tgbotapi.types.message.textsources.*
|
import dev.inmo.tgbotapi.types.message.textsources.*
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
const val testText = "It (is?) is simple hello world with #tag and @mention"
|
const val testText = "It (is?) is simple hello world with #tag and @mention. Start of blockquote: Block quotation started\n" +
|
||||||
const val formattedV2Text = "It \\(is?\\) *_is_ ~__simple__~* ||hello world|| with \\#tag and @mention"
|
"Block quotation continued\n" +
|
||||||
const val formattedHtmlText = "It (is?) <b><i>is</i> <s><u>simple</u></s></b> <span class=\"tg-spoiler\">hello world</span> with #tag and @mention"
|
"The last line of the block quotation"
|
||||||
|
const val formattedV2Text = "It \\(is?\\) *_is_ ~__simple__~* ||hello world|| with \\#tag and @mention\\. Start of blockquote: >Block quotation started\n>Block quotation continued\n>The last line of the block quotation"
|
||||||
|
const val formattedHtmlText = "It (is?) <b><i>is</i> <s><u>simple</u></s></b> <span class=\"tg-spoiler\">hello world</span> with #tag and @mention. Start of blockquote: <blockquote>Block quotation started\nBlock quotation continued\nThe last line of the block quotation</blockquote>"
|
||||||
internal val testTextEntities = listOf(
|
internal val testTextEntities = listOf(
|
||||||
RawMessageEntity(
|
RawMessageEntity(
|
||||||
"bold",
|
"bold",
|
||||||
@ -42,6 +44,11 @@ internal val testTextEntities = listOf(
|
|||||||
"mention",
|
"mention",
|
||||||
45,
|
45,
|
||||||
8
|
8
|
||||||
|
),
|
||||||
|
RawMessageEntity(
|
||||||
|
"blockquote",
|
||||||
|
76,
|
||||||
|
86
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -54,10 +61,15 @@ fun TextSourcesList.testTextSources() {
|
|||||||
assertTrue (get(5) is HashTagTextSource)
|
assertTrue (get(5) is HashTagTextSource)
|
||||||
assertTrue (get(6) is RegularTextSource)
|
assertTrue (get(6) is RegularTextSource)
|
||||||
assertTrue (get(7) is MentionTextSource)
|
assertTrue (get(7) is MentionTextSource)
|
||||||
|
assertTrue (get(8) is RegularTextSource)
|
||||||
|
assertTrue (get(9) is BlockquoteTextSource)
|
||||||
|
|
||||||
val boldSource = get(1) as BoldTextSource
|
val boldSource = get(1) as BoldTextSource
|
||||||
assertTrue (boldSource.subsources.first() is ItalicTextSource)
|
assertTrue (boldSource.subsources.first() is ItalicTextSource)
|
||||||
assertTrue (boldSource.subsources[1] is RegularTextSource)
|
assertTrue (boldSource.subsources[1] is RegularTextSource)
|
||||||
assertTrue (boldSource.subsources[2] is StrikethroughTextSource)
|
assertTrue (boldSource.subsources[2] is StrikethroughTextSource)
|
||||||
assertTrue ((boldSource.subsources[2] as StrikethroughTextSource).subsources.first() is UnderlineTextSource)
|
assertTrue ((boldSource.subsources[2] as StrikethroughTextSource).subsources.first() is UnderlineTextSource)
|
||||||
|
|
||||||
|
val blockquoteSource = get(9) as BlockquoteTextSource
|
||||||
|
assertTrue (blockquoteSource.subsources.first() is RegularTextSource)
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,13 @@ class StringFormattingTests {
|
|||||||
" with " +
|
" with " +
|
||||||
hashtag("tag") +
|
hashtag("tag") +
|
||||||
" and " +
|
" and " +
|
||||||
mention("mention")
|
mention("mention") +
|
||||||
|
". Start of blockquote: " +
|
||||||
|
blockquote(
|
||||||
|
"Block quotation started\n" +
|
||||||
|
"Block quotation continued\n" +
|
||||||
|
"The last line of the block quotation"
|
||||||
|
)
|
||||||
sources.testTextSources()
|
sources.testTextSources()
|
||||||
|
|
||||||
assertEquals(formattedV2Text, sources.toMarkdownV2Texts().first())
|
assertEquals(formattedV2Text, sources.toMarkdownV2Texts().first())
|
||||||
|
Loading…
Reference in New Issue
Block a user