package dev.inmo.tgbotapi.types.message.textsources import dev.inmo.tgbotapi.utils.internal.ClassCastsIncluded import dev.inmo.tgbotapi.types.captionLength import dev.inmo.tgbotapi.types.textLength import kotlinx.serialization.Serializable const val DirectInvocationOfTextSourceConstructor = "It is strongly not recommended to use constructors directly instead of factory methods" typealias TextSourcesList = List typealias MutableTextSourcesList = MutableList @Serializable(TextSourceSerializer::class) @ClassCastsIncluded sealed interface TextSource { val markdown: String val markdownV2: String val html: 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) = 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.plus(text: String) = this + regular(text) @Serializable(TextSourceSerializer::class) sealed interface MultilevelTextSource : TextSource { val subsources: List } fun List.separateForMessage(limit: IntRange, numberOfParts: Int? = null): List> { if (isEmpty()) { return emptyList() } val resultList = mutableListOf>(mutableListOf()) var currentPartLength = 0 val maxSize = limit.last + 1 for (current in this) { if (current.source.length > maxSize) { error("Currently unsupported parts with size more than target one-message parts (${current.source.length} > ${maxSize})") } if (currentPartLength + current.source.length > maxSize) { if (numberOfParts == null || numberOfParts < resultList.size) { resultList.add(mutableListOf()) currentPartLength = 0 } else { break } } resultList.last().add(current) currentPartLength += current.source.length } return resultList } /** * This method will prepare [TextSource]s list for messages. Remember, that first part will be separated with * [captionLength] and all others with */ fun List.separateForCaption(): List> { val captionPart = separateForMessage(captionLength, 1).first() return listOf(captionPart) + minus(captionPart).separateForMessage(textLength) } /** * This method will prepare [TextSource]s list for messages with [textLength] */ @Suppress("NOTHING_TO_INLINE") inline fun List.separateForText(): List> = separateForMessage(textLength)