add simple text dsl for textsources

This commit is contained in:
InsanusMokrassar 2020-11-06 18:52:59 +06:00
parent 54cfea9adf
commit 3620350cc0
29 changed files with 363 additions and 148 deletions

View File

@ -23,4 +23,4 @@ interface CaptionedInput : Captioned {
* Convert its [CaptionedInput.captionEntities] to list of [dev.inmo.tgbotapi.CommonAbstracts.TextSource]
* with [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource]
*/
fun CaptionedInput.fullEntitiesList(): FullTextSourcesList = caption ?.fullListOfSubSource(captionEntities) ?.map { it.source } ?: emptyList()
fun CaptionedInput.fullEntitiesList(): TextSourcesList = caption ?.fullListOfSubSource(captionEntities) ?.map { it.source } ?: emptyList()

View File

@ -29,4 +29,4 @@ interface ExplainedInput : Explained {
* Convert its [ExplainedInput.explanationEntities] to list of [dev.inmo.tgbotapi.CommonAbstracts.TextSource]
* with [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource]
*/
fun ExplainedInput.fullEntitiesList(): FullTextSourcesList = explanation ?.fullListOfSubSource(explanationEntities) ?.map { it.source } ?: emptyList()
fun ExplainedInput.fullEntitiesList(): TextSourcesList = explanation ?.fullListOfSubSource(explanationEntities) ?.map { it.source } ?: emptyList()

View File

@ -1,10 +1,16 @@
package dev.inmo.tgbotapi.CommonAbstracts
import dev.inmo.tgbotapi.types.MessageEntity.textsources.regular
import dev.inmo.tgbotapi.types.MessageEntity.toTextParts
import dev.inmo.tgbotapi.types.captionLength
import dev.inmo.tgbotapi.types.textLength
const val DirectInvocationOfTextSourceConstructor = "It is strongly not recommended to use constructors directly instead of factory methods"
typealias TextSourcesList = List<TextSource>
@Deprecated("All lists of TextSource in public API now are full. So, this typealias is redundant")
typealias FullTextSourcesList = List<TextSource>
@Deprecated("All lists of TextPart in public API now are full. So, this typealias is redundant")
typealias FullTextPartsList = List<TextPart>
interface TextSource {
@ -12,8 +18,19 @@ interface TextSource {
val asMarkdownV2Source: String
val asHtmlSource: String
val source: String
val asText: String
get() = source
}
@Suppress("NOTHING_TO_INLINE")
inline operator fun TextSource.plus(other: TextSource) = listOf(this, other)
@Suppress("NOTHING_TO_INLINE")
inline operator fun TextSource.plus(other: List<TextSource>) = listOf(this) + other
@Suppress("NOTHING_TO_INLINE")
inline operator fun TextSource.plus(text: String) = listOf(this, regular(text))
@Suppress("NOTHING_TO_INLINE")
inline operator fun List<TextSource>.plus(text: String) = this + regular(text)
interface MultilevelTextSource : TextSource {
@Deprecated("Will be removed in near major release")

View File

@ -29,4 +29,4 @@ interface TextedInput : Texted {
* Convert its [TextedInput.textEntities] to list of [dev.inmo.tgbotapi.CommonAbstracts.TextSource]
* with [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource]
*/
fun TextedInput.fullEntitiesList(): FullTextSourcesList = text ?.fullListOfSubSource(textEntities) ?.map { it.source } ?: emptyList()
fun TextedInput.fullEntitiesList(): TextSourcesList = text ?.fullListOfSubSource(textEntities) ?.map { it.source } ?: emptyList()

View File

@ -28,7 +28,7 @@ internal fun RawMessageEntity.asTextParts(
"mention" -> MentionTextSource(sourceSubstring, shiftedSubSources)
"hashtag" -> HashTagTextSource(sourceSubstring, shiftedSubSources)
"cashtag" -> CashTagTextSource(sourceSubstring, shiftedSubSources)
"bot_command" -> BotCommandTextSource(sourceSubstring, shiftedSubSources)
"bot_command" -> BotCommandTextSource(sourceSubstring)
"url" -> URLTextSource(sourceSubstring)
"email" -> EMailTextSource(sourceSubstring, shiftedSubSources)
"phone_number" -> PhoneNumberTextSource(sourceSubstring, shiftedSubSources)
@ -130,6 +130,12 @@ internal fun List<TextSource>.toTextParts(preOffset: Int = 0): List<TextPart> {
}
}
fun String.removeLeading(word: String) = if (startsWith(word)){
substring(word.length)
} else {
this
}
internal fun List<TextSource>.toRawMessageEntities(): List<RawMessageEntity> = toTextParts().asRawMessageEntities()
internal fun RawMessageEntities.asTextParts(sourceString: String): List<TextPart> = sourceString.fullListOfSubSource(

View File

@ -4,7 +4,10 @@ import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.types.MessageEntity.toTextParts
import dev.inmo.tgbotapi.utils.*
class BoldTextSource(
/**
* @see bold
*/
data class BoldTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String,
override val textSources: List<TextSource>
) : MultilevelTextSource {
@ -13,7 +16,9 @@ class BoldTextSource(
override val asHtmlSource: String by lazy { boldHTML() }
}
@Suppress("NOTHING_TO_INLINE")
inline fun bold(text: String) = BoldTextSource(text, emptyList())
@Suppress("NOTHING_TO_INLINE")
inline fun bold(parts: List<TextSource>) = BoldTextSource(parts.makeString(), parts)
@Suppress("NOTHING_TO_INLINE")
inline fun bold(vararg parts: TextSource) = bold(parts.toList())
@Suppress("NOTHING_TO_INLINE")
inline fun bold(text: String) = bold(regular(text))

View File

@ -1,19 +1,28 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.types.MessageEntity.removeLeading
import dev.inmo.tgbotapi.utils.*
private val commandRegex = Regex("[/!][^@\\s]*")
class BotCommandTextSource(
override val source: String,
override val textSources: List<TextSource>
) : MultilevelTextSource {
/**
* @see botCommand
*/
data class BotCommandTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String
) : TextSource {
val command: String by lazy {
commandRegex.find(source) ?.value ?.substring(1) ?: source.substring(1)// skip first symbol like "/" or "!"
}
override val asMarkdownSource: String by lazy { source.commandMarkdown() }
override val asMarkdownV2Source: String by lazy { commandMarkdownV2() }
override val asHtmlSource: String by lazy { commandHTML() }
override val asMarkdownV2Source: String by lazy { source.commandMarkdownV2() }
override val asHtmlSource: String by lazy { source.commandHTML() }
}
/**
* @param command Without leading "/"
*/
@Suppress("NOTHING_TO_INLINE")
inline fun botCommand(command: String) = BotCommandTextSource("/$command")

View File

@ -3,7 +3,10 @@ package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.utils.*
class CashTagTextSource(
/**
* @see cashTag
*/
data class CashTagTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String,
override val textSources: List<TextSource>
) : MultilevelTextSource {
@ -11,3 +14,10 @@ class CashTagTextSource(
override val asMarkdownV2Source: String by lazy { cashTagMarkdownV2() }
override val asHtmlSource: String by lazy { cashTagHTML() }
}
@Suppress("NOTHING_TO_INLINE")
inline fun cashTag(parts: List<TextSource>) = CashTagTextSource(parts.makeString(), parts)
@Suppress("NOTHING_TO_INLINE")
inline fun cashTag(vararg parts: TextSource) = cashTag(parts.toList())
@Suppress("NOTHING_TO_INLINE")
inline fun cashTag(tag: String) = cashTag(regular(tag))

View File

@ -1,12 +1,19 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.DirectInvocationOfTextSourceConstructor
import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.utils.*
class CodeTextSource(
/**
* @see code
*/
data class CodeTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String
) : TextSource {
override val asMarkdownSource: String by lazy { source.codeMarkdown() }
override val asMarkdownV2Source: String by lazy { source.codeMarkdownV2() }
override val asHtmlSource: String by lazy { source.codeHTML() }
}
@Suppress("NOTHING_TO_INLINE")
inline fun code(code: String) = CodeTextSource(code)

View File

@ -3,7 +3,10 @@ package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.utils.*
class EMailTextSource(
/**
* @see email
*/
data class EMailTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String,
override val textSources: List<TextSource>
) : MultilevelTextSource {
@ -11,3 +14,10 @@ class EMailTextSource(
override val asMarkdownV2Source: String by lazy { emailMarkdownV2(source) }
override val asHtmlSource: String by lazy { emailHTML(source) }
}
@Suppress("NOTHING_TO_INLINE")
inline fun email(parts: List<TextSource>) = EMailTextSource(parts.makeString(), parts)
@Suppress("NOTHING_TO_INLINE")
inline fun email(vararg parts: TextSource) = email(parts.toList())
@Suppress("NOTHING_TO_INLINE")
inline fun email(emailAddress: String) = email(regular(emailAddress))

View File

@ -3,18 +3,30 @@ package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.utils.*
private val String.withoutSharp
get() = if (startsWith("#")){
substring(1)
} else {
this
}
class HashTagTextSource(
/**
* @see hashtag
*/
data class HashTagTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String,
override val textSources: List<TextSource>
) : MultilevelTextSource {
override val asMarkdownSource: String by lazy { source.hashTagMarkdown() }
override val asMarkdownV2Source: String by lazy { hashTagMarkdownV2() }
override val asHtmlSource: String by lazy { hashTagHTML() }
init {
if (!source.startsWith("#")) {
error("HashTag source must starts with #, but actual value is \"$source\"")
}
}
}
@Suppress("NOTHING_TO_INLINE", "EXPERIMENTAL_API_USAGE")
inline fun hashtag(parts: List<TextSource>) = (regular("#") + parts).let { HashTagTextSource(it.makeString(), it) }
@Suppress("NOTHING_TO_INLINE")
inline fun hashtag(vararg parts: TextSource) = hashtag(parts.toList())
/**
* Without sharp (#)
*/
@Suppress("NOTHING_TO_INLINE")
inline fun hashtag(hashtag: String) = hashtag(regular(hashtag))

View File

@ -3,7 +3,10 @@ package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.utils.*
class ItalicTextSource(
/**
* @see italic
*/
data class ItalicTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String,
override val textSources: List<TextSource>
) : MultilevelTextSource {
@ -11,3 +14,11 @@ class ItalicTextSource(
override val asMarkdownV2Source: String by lazy { italicMarkdownV2() }
override val asHtmlSource: String by lazy { italicHTML() }
}
@Suppress("NOTHING_TO_INLINE")
inline fun italic(parts: List<TextSource>) = ItalicTextSource(parts.makeString(), parts)
@Suppress("NOTHING_TO_INLINE")
inline fun italic(vararg parts: TextSource) = italic(parts.toList())
@Suppress("NOTHING_TO_INLINE")
inline fun italic(text: String) = italic(regular(text))

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.types.MessageEntity.removeLeading
import dev.inmo.tgbotapi.utils.*
private val String.withoutCommercialAt
@ -10,11 +11,32 @@ private val String.withoutCommercialAt
this
}
class MentionTextSource(
/**
* @see mention
*/
data class MentionTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String,
override val textSources: List<TextSource>
) : MultilevelTextSource {
override val asMarkdownSource: String by lazy { source.mentionMarkdown() }
override val asMarkdownV2Source: String by lazy { mentionMarkdownV2() }
override val asHtmlSource: String by lazy { mentionHTML() }
init {
if (!source.startsWith("@")) {
error("Mention source must starts with @, but actual value is \"$source\"")
}
}
}
@Suppress("NOTHING_TO_INLINE")
inline fun mention(parts: List<TextSource>) = (regular("@") + parts).let { MentionTextSource(it.makeString(), it) }
@Suppress("NOTHING_TO_INLINE")
inline fun mention(vararg parts: TextSource) = mention(parts.toList())
/**
* Without leading "@"
*/
@Suppress("NOTHING_TO_INLINE")
inline fun mention(whoToMention: String) = mention(regular(whoToMention))

View File

@ -3,7 +3,10 @@ package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.utils.*
class PhoneNumberTextSource(
/**
* @see phone
*/
data class PhoneNumberTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String,
override val textSources: List<TextSource>
) : MultilevelTextSource {
@ -11,3 +14,11 @@ class PhoneNumberTextSource(
override val asMarkdownV2Source: String by lazy { phoneMarkdownV2() }
override val asHtmlSource: String by lazy { phoneHTML() }
}
@Suppress("NOTHING_TO_INLINE")
inline fun phone(parts: List<TextSource>) = PhoneNumberTextSource(parts.makeString(), parts)
@Suppress("NOTHING_TO_INLINE")
inline fun phone(vararg parts: TextSource) = phone(parts.toList())
@Suppress("NOTHING_TO_INLINE")
inline fun phone(number: String) = phone(regular(number))

View File

@ -1,9 +1,12 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.utils.*
class PreTextSource(
/**
* @see pre
*/
data class PreTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String,
val language: String? = null
) : TextSource {
@ -11,3 +14,7 @@ class PreTextSource(
override val asMarkdownV2Source: String by lazy { source.preMarkdownV2(language) }
override val asHtmlSource: String by lazy { source.preHTML(language) }
}
@Suppress("NOTHING_TO_INLINE")
inline fun pre(code: String, language: String? = null) = PreTextSource(code, language)

View File

@ -1,12 +1,18 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.utils.*
class RegularTextSource(
/**
* @see regular
*/
data class RegularTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String
) : TextSource {
override val asMarkdownSource: String by lazy { source.regularMarkdown() }
override val asMarkdownV2Source: String by lazy { source.regularMarkdownV2() }
override val asHtmlSource: String by lazy { source.regularHtml() }
}
@Suppress("NOTHING_TO_INLINE")
inline fun regular(text: String) = RegularTextSource(text)

View File

@ -3,11 +3,21 @@ package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.utils.*
class StrikethroughTextSource(
/**
* @see strikethrough
*/
data class StrikethroughTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String,
override val textSources: List<TextSource>
) : MultilevelTextSource {
override val asHtmlSource: String by lazy { strikethroughHTML() }
override val asMarkdownV2Source: String by lazy { strikethroughMarkdownV2() }
override val asMarkdownSource: String by lazy { source.strikethroughMarkdown() }
}
}
@Suppress("NOTHING_TO_INLINE")
inline fun strikethrough(parts: List<TextSource>) = StrikethroughTextSource(parts.makeString(), parts)
@Suppress("NOTHING_TO_INLINE")
inline fun strikethrough(vararg parts: TextSource) = strikethrough(parts.toList())
@Suppress("NOTHING_TO_INLINE")
inline fun strikethrough(text: String) = strikethrough(regular(text))

View File

@ -1,9 +1,12 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.utils.*
class TextLinkTextSource(
/**
* @see link
*/
data class TextLinkTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String,
val url: String
) : TextSource {
@ -11,3 +14,6 @@ class TextLinkTextSource(
override val asMarkdownV2Source: String by lazy { source.linkMarkdownV2(url) }
override val asHtmlSource: String by lazy { source.linkHTML(url) }
}
@Suppress("NOTHING_TO_INLINE")
inline fun link(text: String, url: String) = TextLinkTextSource(text, url)

View File

@ -4,7 +4,10 @@ import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.types.User
import dev.inmo.tgbotapi.utils.*
class TextMentionTextSource(
/**
* @see mention
*/
data class TextMentionTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String,
val user: User,
override val textSources: List<TextSource>
@ -13,3 +16,10 @@ class TextMentionTextSource(
override val asMarkdownV2Source: String by lazy { textMentionMarkdownV2(user.id) }
override val asHtmlSource: String by lazy { textMentionHTML(user.id) }
}
@Suppress("NOTHING_TO_INLINE")
inline fun mention(parts: List<TextSource>, user: User) = TextMentionTextSource(parts.makeString(), user, parts)
@Suppress("NOTHING_TO_INLINE")
inline fun mention(user: User, vararg parts: TextSource) = mention(parts.toList(), user)
@Suppress("NOTHING_TO_INLINE")
inline fun mention(text: String, user: User) = mention(user, regular(text))

View File

@ -1,12 +1,18 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.utils.*
class URLTextSource(
/**
* @see link
*/
data class URLTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String
) : TextSource {
override val asMarkdownSource: String by lazy { source.linkMarkdown(source) }
override val asMarkdownV2Source: String by lazy { source.linkMarkdownV2(source) }
override val asHtmlSource: String by lazy { source.linkHTML(source) }
}
@Suppress("NOTHING_TO_INLINE")
inline fun link(url: String) = URLTextSource(url)

View File

@ -3,11 +3,21 @@ package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.utils.*
class UnderlineTextSource(
/**
* @see underline
*/
data class UnderlineTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String,
override val textSources: List<TextSource>
) : MultilevelTextSource {
override val asMarkdownSource: String by lazy { source.underlineMarkdown() }
override val asMarkdownV2Source: String by lazy { underlineMarkdownV2() }
override val asHtmlSource: String by lazy { underlineHTML() }
}
}
@Suppress("NOTHING_TO_INLINE")
inline fun underline(parts: List<TextSource>) = UnderlineTextSource(parts.makeString(), parts)
@Suppress("NOTHING_TO_INLINE")
inline fun underline(vararg parts: TextSource) = underline(parts.toList())
@Suppress("NOTHING_TO_INLINE")
inline fun underline(text: String) = underline(regular(text))

View File

@ -1,6 +1,6 @@
package dev.inmo.tgbotapi.types.message.content
import dev.inmo.tgbotapi.CommonAbstracts.FullTextSourcesList
import dev.inmo.tgbotapi.CommonAbstracts.TextSourcesList
import dev.inmo.tgbotapi.CommonAbstracts.TextPart
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.requests.send.SendTextMessage
@ -81,4 +81,4 @@ data class TextContent(
* Convert its [TextContent.entities] to list of [dev.inmo.tgbotapi.CommonAbstracts.TextSource]
* with [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource]
*/
fun TextContent.fullEntitiesList(): FullTextSourcesList = text.fullListOfSubSource(entities).map { it.source }
fun TextContent.fullEntitiesList(): TextSourcesList = text.fullListOfSubSource(entities).map { it.source }

View File

@ -7,7 +7,7 @@ import dev.inmo.tgbotapi.types.message.content.TextContent
import dev.inmo.tgbotapi.types.message.content.fullEntitiesList
internal fun createFormattedText(
entities: FullTextSourcesList,
entities: TextSourcesList,
partLength: Int = textLength.last,
mode: ParseMode = MarkdownParseMode
): List<String> {
@ -48,17 +48,17 @@ internal fun createFormattedText(
internal fun createMarkdownText(
entities: FullTextSourcesList,
entities: TextSourcesList,
partLength: Int = textLength.last
): List<String> = createFormattedText(entities, partLength, MarkdownParseMode)
internal fun FullTextSourcesList.toMarkdownTexts(): List<String> = createMarkdownText(
internal fun TextSourcesList.toMarkdownTexts(): List<String> = createMarkdownText(
this,
textLength.last
)
internal fun TextContent.toMarkdownTexts(): List<String> = fullEntitiesList().toMarkdownTexts()
internal fun FullTextSourcesList.toMarkdownExplanations(): List<String> = createMarkdownText(
internal fun TextSourcesList.toMarkdownExplanations(): List<String> = createMarkdownText(
this,
explanationLimit.last
)
@ -66,23 +66,23 @@ internal fun ExplainedInput.toMarkdownExplanations(): List<String> = fullEntitie
internal fun createMarkdownV2Text(
entities: FullTextSourcesList,
entities: TextSourcesList,
partLength: Int = textLength.last
): List<String> = createFormattedText(entities, partLength, MarkdownV2ParseMode)
internal fun FullTextSourcesList.toMarkdownV2Captions(): List<String> = createMarkdownV2Text(
internal fun TextSourcesList.toMarkdownV2Captions(): List<String> = createMarkdownV2Text(
this,
captionLength.last
)
internal fun CaptionedInput.toMarkdownV2Captions(): List<String> = fullEntitiesList().toMarkdownV2Captions()
internal fun FullTextSourcesList.toMarkdownV2Texts(): List<String> = createMarkdownV2Text(
internal fun TextSourcesList.toMarkdownV2Texts(): List<String> = createMarkdownV2Text(
this,
textLength.last
)
internal fun TextContent.toMarkdownV2Texts(): List<String> = fullEntitiesList().toMarkdownV2Texts()
internal fun FullTextSourcesList.toMarkdownV2Explanations(): List<String> = createMarkdownV2Text(
internal fun TextSourcesList.toMarkdownV2Explanations(): List<String> = createMarkdownV2Text(
this,
explanationLimit.last
)
@ -90,17 +90,17 @@ internal fun ExplainedInput.toMarkdownV2Explanations(): List<String> = fullEntit
internal fun createHtmlText(
entities: FullTextSourcesList,
entities: TextSourcesList,
partLength: Int = textLength.last
): List<String> = createFormattedText(entities, partLength, HTMLParseMode)
internal fun FullTextSourcesList.toHtmlCaptions(): List<String> = createHtmlText(
internal fun TextSourcesList.toHtmlCaptions(): List<String> = createHtmlText(
this,
captionLength.last
)
internal fun CaptionedInput.toHtmlCaptions(): List<String> = fullEntitiesList().toHtmlCaptions()
internal fun FullTextSourcesList.toHtmlTexts(): List<String> = createHtmlText(
internal fun TextSourcesList.toHtmlTexts(): List<String> = createHtmlText(
this,
textLength.last
)

View File

@ -98,6 +98,16 @@ internal fun MultilevelTextSource.linkHTML(
) = "<a href=\"${link.toHtml()}\">${textSources.joinSubSourcesHtml()}</a>"
internal fun MultilevelTextSource.optionalPrefix(
mustStartsWith: String,
controlWord: String = mustStartsWith
) = if (source.startsWith(mustStartsWith)) {
""
} else {
controlWord
}
internal fun MultilevelTextSource.emailMarkdownV2(address: String): String = linkMarkdownV2("mailto://$address")
internal fun MultilevelTextSource.emailHTML(address: String): String = linkHTML("mailto://$address}")
@ -125,18 +135,21 @@ internal fun MultilevelTextSource.underlineHTML(): String = htmlDefault(htmlUnde
internal fun MultilevelTextSource.textMentionMarkdownV2(userId: UserId): String = linkMarkdownV2(userId.link)
internal fun MultilevelTextSource.textMentionHTML(userId: UserId): String = linkHTML(userId.link)
internal fun MultilevelTextSource.mentionMarkdownV2(): String = "@${textSources.joinSubSourcesMarkdownV2()}"
internal fun MultilevelTextSource.mentionHTML(): String = "@${textSources.joinSubSourcesHtml()}"
internal fun MultilevelTextSource.mentionMarkdownV2(): String = optionalPrefix("@") + textSources.joinSubSourcesMarkdownV2()
internal fun MultilevelTextSource.mentionHTML(): String = optionalPrefix("@") + textSources.joinSubSourcesHtml()
internal fun MultilevelTextSource.hashTagMarkdownV2(): String = "\\#${textSources.joinSubSourcesMarkdownV2()}"
internal fun MultilevelTextSource.hashTagHTML(): String = "#${textSources.joinSubSourcesHtml()}"
internal fun MultilevelTextSource.hashTagMarkdownV2(): String = when {
source.startsWith("\\#") || source.startsWith("#") -> ""
else -> "\\#"
} + textSources.joinSubSourcesMarkdownV2()
internal fun MultilevelTextSource.hashTagHTML(): String = optionalPrefix("#") + textSources.joinSubSourcesHtml()
internal fun MultilevelTextSource.phoneMarkdownV2(): String = textSources.joinSubSourcesMarkdownV2()
internal fun MultilevelTextSource.phoneHTML(): String = textSources.joinSubSourcesHtml()
internal fun MultilevelTextSource.commandMarkdownV2(): String = "/${textSources.joinSubSourcesMarkdownV2()}"
internal fun MultilevelTextSource.commandHTML(): String = "/${textSources.joinSubSourcesHtml()}"
internal fun MultilevelTextSource.commandMarkdownV2(): String = optionalPrefix("/") + textSources.joinSubSourcesMarkdownV2()
internal fun MultilevelTextSource.commandHTML(): String = optionalPrefix("/") + textSources.joinSubSourcesHtml()

View File

@ -0,0 +1,56 @@
package dev.inmo.tgbotapi.types.MessageEntity
import dev.inmo.tgbotapi.CommonAbstracts.TextPart
import dev.inmo.tgbotapi.types.MessageEntity.textsources.*
import kotlin.test.assertTrue
const val testText = "It is simple hello world with #tag and @mention"
const val formattedV2Text = "It *_is_ ~__simple__~* hello world with \\#tag and @mention"
const val formattedHtmlText = "It <b><i>is</i> <s><u>simple</u></s></b> hello world with #tag and @mention"
internal val testTextEntities = listOf(
RawMessageEntity(
"bold",
3,
9
),
RawMessageEntity(
"italic",
3,
2
),
RawMessageEntity(
"strikethrough",
6,
6
),
RawMessageEntity(
"underline",
6,
6
),
RawMessageEntity(
"hashtag",
30,
4
),
RawMessageEntity(
"mention",
39,
6
)
)
fun List<TextPart>.testTextParts() {
assertTrue (first().source is RegularTextSource)
assertTrue (get(1).source is BoldTextSource)
assertTrue (get(2).source is RegularTextSource)
assertTrue (get(3).source is HashTagTextSource)
assertTrue (get(4).source is RegularTextSource)
assertTrue (get(5).source is MentionTextSource)
val boldSource = get(1).source as BoldTextSource
assertTrue (boldSource.textSources.first() is ItalicTextSource)
assertTrue (boldSource.textSources[1] is RegularTextSource)
assertTrue (boldSource.textSources[2] is StrikethroughTextSource)
assertTrue ((boldSource.textSources[2] as StrikethroughTextSource).textSources.first() is UnderlineTextSource)
}

View File

@ -1,5 +1,9 @@
package dev.inmo.tgbotapi.utils
package dev.inmo.tgbotapi.types.MessageEntity
import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.types.MessageEntity.textsources.*
import dev.inmo.tgbotapi.CommonAbstracts.plus
import dev.inmo.tgbotapi.utils.*
import kotlin.test.Test
import kotlin.test.assertEquals
@ -33,4 +37,20 @@ class StringFormattingTests {
originalHelloWorld.preMarkdown()
)
}
@Test
fun testThatCreatingOfStringWithSimpleDSLWorksCorrectly() {
val sources: List<TextSource> = regular("It ") +
bold(italic("is") +
" " +
strikethrough(underline("simple"))) +
" hello world with " +
hashtag("tag") +
" and " +
mention("mention")
sources.toTextParts().testTextParts()
assertEquals(formattedV2Text, sources.toMarkdownV2Texts().first())
assertEquals(formattedHtmlText, sources.toHtmlTexts().first())
}
}

View File

@ -8,42 +8,8 @@ import kotlin.test.*
class TextPartsCreatingTests {
@Test
fun testThatTextWithMultilevelPartsCorrectlyCreating() {
val text = "It is simple hello world"
val formattedV2Text = "It *_is_ ~__simple__~* hello world"
val entities = listOf(
RawMessageEntity(
"bold",
3,
9
),
RawMessageEntity(
"italic",
3,
2
),
RawMessageEntity(
"strikethrough",
6,
6
),
RawMessageEntity(
"underline",
6,
6
)
)
val textParts = entities.asTextParts(text)
assertTrue (textParts.first().source is RegularTextSource)
assertTrue (textParts[1].source is BoldTextSource)
assertTrue (textParts[2].source is RegularTextSource)
val boldSource = textParts[1].source as BoldTextSource
assertTrue (boldSource.textSources.first() is ItalicTextSource)
assertTrue (boldSource.textSources[1] is RegularTextSource)
assertTrue (boldSource.textSources[2] is StrikethroughTextSource)
assertTrue ((boldSource.textSources[2] as StrikethroughTextSource).textSources.first() is UnderlineTextSource)
val textParts = testTextEntities.asTextParts(testText)
textParts.testTextParts()
assertEquals(
formattedV2Text,
@ -53,42 +19,8 @@ class TextPartsCreatingTests {
@Test
fun testThatTextWithMultilevelPartsCorrectlyCreatingInHtml() {
val text = "It is simple hello world"
val formattedHtmlText = "It <b><i>is</i> <s><u>simple</u></s></b> hello world"
val entities = listOf(
RawMessageEntity(
"bold",
3,
9
),
RawMessageEntity(
"italic",
3,
2
),
RawMessageEntity(
"strikethrough",
6,
6
),
RawMessageEntity(
"underline",
6,
6
)
)
val textParts = entities.asTextParts(text)
assertTrue (textParts.first().source is RegularTextSource)
assertTrue (textParts[1].source is BoldTextSource)
assertTrue (textParts[2].source is RegularTextSource)
val boldSource = textParts[1].source as BoldTextSource
assertTrue (boldSource.textSources.first() is ItalicTextSource)
assertTrue (boldSource.textSources[1] is RegularTextSource)
assertTrue (boldSource.textSources[2] is StrikethroughTextSource)
assertTrue ((boldSource.textSources[2] as StrikethroughTextSource).textSources.first() is UnderlineTextSource)
val textParts = testTextEntities.asTextParts(testText)
textParts.testTextParts()
assertEquals(
formattedHtmlText,

View File

@ -8,12 +8,22 @@ import io.ktor.client.HttpClient
import io.ktor.client.HttpClientConfig
import io.ktor.client.engine.*
/**
* Allows to create bot using bot [urlsKeeper]
*/
fun telegramBot(
urlsKeeper: TelegramAPIUrlsKeeper
): TelegramBot = KtorRequestsExecutor(
urlsKeeper,
HttpClient()
)
/**
* Allows to create bot using bot [urlsKeeper] and already prepared [client]
*/
fun telegramBot(
urlsKeeper: TelegramAPIUrlsKeeper,
client: HttpClient = HttpClient()
client: HttpClient
): TelegramBot = KtorRequestsExecutor(
urlsKeeper,
client
@ -60,6 +70,15 @@ inline fun telegramBot(
HttpClient(clientConfig)
)
/**
* Allows to create bot using bot [token], [apiUrl] (for custom api servers) and already prepared [client]
*/
@Suppress("NOTHING_TO_INLINE")
inline fun telegramBot(
token: String,
apiUrl: String = telegramBotAPIDefaultUrl
): TelegramBot = telegramBot(TelegramAPIUrlsKeeper(token, apiUrl))
/**
* Allows to create bot using bot [token], [apiUrl] (for custom api servers) and already prepared [client]
*/
@ -67,7 +86,7 @@ inline fun telegramBot(
inline fun telegramBot(
token: String,
apiUrl: String = telegramBotAPIDefaultUrl,
client: HttpClient = HttpClient()
client: HttpClient
): TelegramBot = telegramBot(TelegramAPIUrlsKeeper(token, apiUrl), client)
@Suppress("NOTHING_TO_INLINE")
@ -106,7 +125,7 @@ inline fun telegramBot(
inline fun telegramBot(
token: String,
apiUrl: String = telegramBotAPIDefaultUrl,
noinline clientConfig: HttpClientConfig<*>.() -> Unit = {}
noinline clientConfig: HttpClientConfig<*>.() -> Unit
) = telegramBot(
TelegramAPIUrlsKeeper(token, apiUrl),
clientConfig

View File

@ -7,7 +7,7 @@ import dev.inmo.tgbotapi.types.message.content.TextContent
import dev.inmo.tgbotapi.types.message.content.fullEntitiesList
fun createFormattedText(
entities: FullTextSourcesList,
entities: TextSourcesList,
partLength: Int = textLength.last,
mode: ParseMode = MarkdownParseMode
): List<String> {
@ -48,23 +48,23 @@ fun createFormattedText(
fun createMarkdownText(
entities: FullTextSourcesList,
entities: TextSourcesList,
partLength: Int = textLength.last
): List<String> = createFormattedText(entities, partLength, MarkdownParseMode)
fun FullTextSourcesList.toMarkdownCaptions(): List<String> = createMarkdownText(
fun TextSourcesList.toMarkdownCaptions(): List<String> = createMarkdownText(
this,
captionLength.last
)
fun CaptionedInput.toMarkdownCaptions(): List<String> = fullEntitiesList().toMarkdownCaptions()
fun FullTextSourcesList.toMarkdownTexts(): List<String> = createMarkdownText(
fun TextSourcesList.toMarkdownTexts(): List<String> = createMarkdownText(
this,
textLength.last
)
fun TextContent.toMarkdownTexts(): List<String> = fullEntitiesList().toMarkdownTexts()
fun FullTextSourcesList.toMarkdownExplanations(): List<String> = createMarkdownText(
fun TextSourcesList.toMarkdownExplanations(): List<String> = createMarkdownText(
this,
explanationLimit.last
)
@ -72,23 +72,23 @@ fun ExplainedInput.toMarkdownExplanations(): List<String> = fullEntitiesList().t
fun createMarkdownV2Text(
entities: FullTextSourcesList,
entities: TextSourcesList,
partLength: Int = textLength.last
): List<String> = createFormattedText(entities, partLength, MarkdownV2ParseMode)
fun FullTextSourcesList.toMarkdownV2Captions(): List<String> = createMarkdownV2Text(
fun TextSourcesList.toMarkdownV2Captions(): List<String> = createMarkdownV2Text(
this,
captionLength.last
)
fun CaptionedInput.toMarkdownV2Captions(): List<String> = fullEntitiesList().toMarkdownV2Captions()
fun FullTextSourcesList.toMarkdownV2Texts(): List<String> = createMarkdownV2Text(
fun TextSourcesList.toMarkdownV2Texts(): List<String> = createMarkdownV2Text(
this,
textLength.last
)
fun TextContent.toMarkdownV2Texts(): List<String> = fullEntitiesList().toMarkdownV2Texts()
fun FullTextSourcesList.toMarkdownV2Explanations(): List<String> = createMarkdownV2Text(
fun TextSourcesList.toMarkdownV2Explanations(): List<String> = createMarkdownV2Text(
this,
explanationLimit.last
)
@ -96,23 +96,23 @@ fun ExplainedInput.toMarkdownV2Explanations(): List<String> = fullEntitiesList()
fun createHtmlText(
entities: FullTextSourcesList,
entities: TextSourcesList,
partLength: Int = textLength.last
): List<String> = createFormattedText(entities, partLength, HTMLParseMode)
fun FullTextSourcesList.toHtmlCaptions(): List<String> = createHtmlText(
fun TextSourcesList.toHtmlCaptions(): List<String> = createHtmlText(
this,
captionLength.last
)
fun CaptionedInput.toHtmlCaptions(): List<String> = fullEntitiesList().toHtmlCaptions()
fun FullTextSourcesList.toHtmlTexts(): List<String> = createHtmlText(
fun TextSourcesList.toHtmlTexts(): List<String> = createHtmlText(
this,
textLength.last
)
fun TextContent.toHtmlTexts(): List<String> = fullEntitiesList().toHtmlTexts()
fun FullTextSourcesList.toHtmlExplanations(): List<String> = createHtmlText(
fun TextSourcesList.toHtmlExplanations(): List<String> = createHtmlText(
this,
explanationLimit.last
)