diff --git a/CHANGELOG.md b/CHANGELOG.md index bc1f8e980d..bf0baa7cd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,6 +67,10 @@ * New request `CopyMessage` * New extension `List#makeString` for more comfortable work with new api with entities * Support for Google Places identifiers for venues + * New extensions for text sources separating: + * `List#separateForMessage` + * `List#separateForCaption` + * `List#separateForText` * `API`: * Extensions `TelegramBot#pinChatMessage` now support any `Chat` and `Message`s from any `Chat` * New extensions `TelegramBot#unpinAllChatMessages` diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/CommonAbstracts/TextSource.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/CommonAbstracts/TextSource.kt index c652a3aac8..fbf2541d6e 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/CommonAbstracts/TextSource.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/CommonAbstracts/TextSource.kt @@ -1,5 +1,8 @@ package dev.inmo.tgbotapi.CommonAbstracts +import dev.inmo.tgbotapi.types.captionLength +import dev.inmo.tgbotapi.types.textLength + typealias FullTextSourcesList = List typealias FullTextPartsList = List @@ -22,3 +25,47 @@ data class TextPart( fun List.justTextSources() = map { it.source } fun List.makeString() = joinToString("") { it.source } +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)