diff --git a/CHANGELOG.md b/CHANGELOG.md index 0adf2b8077..04a9c2c6fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,18 @@ * Add `RequestLimiter` and base realisations * Now `KtorRequestsExecutor` can receive as one of parameters `RequestLimiter` (by default - `EmptyLimiter`) +### 0.9.1 + +* Updated built-in lengths restrictions +* Apply restrictions of text limit for sending messages +* Add `RegularTextMessageEntity` which is useful for representing regular text message entity +* Add `convertToFullMessageEntityList` which create list of entities with `RegularTextMessageEntity` on places where +must be regular text +* Change signature of `createMarkdownText`: now it will return list of strings +* Deprecate old signatures of `createMarkdownText`, `toMarkdownCaption`, `toMarkdownText` +* Add `ResendableContent#createResends` which create adapted list of resends for content +* Add `TextContent` own `createResends` realisation + ### 0.8.5 * Add extension `String#toMarkdown` diff --git a/build.gradle b/build.gradle index 4b60baaa21..42460f767d 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -project.version = "0.9.0" +project.version = "0.9.1" project.group = "com.github.insanusmokrassar" buildscript { diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/SendMessage.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/SendMessage.kt index 4216548fb4..1e6c7b5d8e 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/SendMessage.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/SendMessage.kt @@ -35,6 +35,11 @@ data class SendMessage( TextableSendMessageRequest, DisableWebPagePreview { + init { + if (text.length !in textLength) { + throw IllegalArgumentException("Text must be in $textLength range") + } + } override fun method(): String = "sendMessage" override fun resultSerializer(): KSerializer = RawMessage.serializer() diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendAnimation.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendAnimation.kt index 993fc8e2a7..175a63a7f6 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendAnimation.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendAnimation.kt @@ -95,6 +95,13 @@ data class SendAnimationData internal constructor( DuratedSendMessageRequest, SizedSendMessageRequest { + init { + text ?.let { + if (it.length !in captionLength) { + throw IllegalArgumentException("Caption must be in $captionLength range") + } + } + } override fun method(): String = "sendAnimation" override fun resultSerializer(): KSerializer = RawMessage.serializer() diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendAudio.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendAudio.kt index 653621b317..82df382757 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendAudio.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendAudio.kt @@ -95,6 +95,13 @@ data class SendAudioData internal constructor( TitledSendMessageRequest, DuratedSendMessageRequest { + init { + text ?.let { + if (it.length !in captionLength) { + throw IllegalArgumentException("Caption must be in $captionLength range") + } + } + } override fun method(): String = "sendAudio" override fun resultSerializer(): KSerializer = RawMessage.serializer() diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendDocument.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendDocument.kt index 05f22cc523..55e2c67357 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendDocument.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendDocument.kt @@ -78,6 +78,13 @@ data class SendDocumentData internal constructor( TextableSendMessageRequest, ThumbedSendMessageRequest { + init { + text ?.let { + if (it.length !in captionLength) { + throw IllegalArgumentException("Caption must be in $captionLength range") + } + } + } override fun method(): String = "sendDocument" override fun resultSerializer(): KSerializer = RawMessage.serializer() diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendPhoto.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendPhoto.kt index a00684817b..2d5abe34c7 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendPhoto.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendPhoto.kt @@ -63,6 +63,14 @@ data class SendPhotoData internal constructor( ReplyingMarkupSendMessageRequest, TextableSendMessageRequest { + init { + text ?.let { + if (it.length !in captionLength) { + throw IllegalArgumentException("Caption must be in $captionLength range") + } + } + } + override fun method(): String = "sendPhoto" override fun resultSerializer(): KSerializer = RawMessage.serializer() } diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendVideo.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendVideo.kt index cdacb0f009..884c22c12a 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendVideo.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendVideo.kt @@ -100,6 +100,13 @@ data class SendVideoData internal constructor( DuratedSendMessageRequest, SizedSendMessageRequest { + init { + text ?.let { + if (it.length !in captionLength) { + throw IllegalArgumentException("Caption must be in $captionLength range") + } + } + } override fun method(): String = "sendVideo" override fun resultSerializer(): KSerializer = RawMessage.serializer() diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendVideoNote.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendVideoNote.kt index 3bedeec3c1..61d876b225 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendVideoNote.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendVideoNote.kt @@ -94,6 +94,13 @@ data class SendVideoNoteData internal constructor( override val height: Int? get() = width + init { + text ?.let { + if (it.length !in captionLength) { + throw IllegalArgumentException("Caption must be in $captionLength range") + } + } + } override fun method(): String = "sendVideoNote" override fun resultSerializer(): KSerializer = RawMessage.serializer() diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendVoice.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendVoice.kt index 2db410591b..175135b727 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendVoice.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/requests/send/media/SendVoice.kt @@ -84,6 +84,13 @@ data class SendVoiceData internal constructor( ThumbedSendMessageRequest, DuratedSendMessageRequest { + init { + text ?.let { + if (it.length !in captionLength) { + throw IllegalArgumentException("Caption must be in $captionLength range") + } + } + } override fun method(): String = "sendVoice" override fun resultSerializer(): KSerializer = RawMessage.serializer() diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/Common.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/Common.kt index 8e5431c570..e9e28b1d50 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/Common.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/Common.kt @@ -16,17 +16,17 @@ typealias ShippingOptionIdentifier = String typealias StartParameter = String typealias InlineMessageIdentifier = String -val callbackQueryAnswerLength = 0 .. 200 -val captionLength = 0 .. 1024 -val textLength = 0 .. 4096 +val callbackQueryAnswerLength = 0 until 200 +val captionLength = 0 until 1024 +val textLength = 0 until 4096 val userProfilePhotosRequestLimit = 0 .. 100 -val chatTitleLength = 1 .. 255 -val chatDescriptionLength = 0 .. 255 -val inlineResultQueryIdLingth = 1 .. 64 +val chatTitleLength = 1 until 255 +val chatDescriptionLength = 0 until 256 +val inlineResultQueryIdLingth = 1 until 64 -val invoiceTitleLimit = 1 .. 32 -val invoiceDescriptionLimit = 1 .. 255 -val invoicePayloadBytesLimit = 1 .. 128 +val invoiceTitleLimit = 1 until 32 +val invoiceDescriptionLimit = 1 until 256 +val invoicePayloadBytesLimit = 1 until 128 const val chatIdField = "chat_id" const val messageIdField = "message_id" diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/MessageEntity/RegularTextMessageEntity.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/MessageEntity/RegularTextMessageEntity.kt new file mode 100644 index 0000000000..5c899b71e8 --- /dev/null +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/MessageEntity/RegularTextMessageEntity.kt @@ -0,0 +1,7 @@ +package com.github.insanusmokrassar.TelegramBotAPI.types.MessageEntity + +data class RegularTextMessageEntity( + override val offset: Int, + override val length: Int, + override val sourceString: String +) : MessageEntity diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/message/content/TextContent.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/message/content/TextContent.kt index 7c1bb551b3..005aece25d 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/message/content/TextContent.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/message/content/TextContent.kt @@ -10,6 +10,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup import com.github.insanusmokrassar.TelegramBotAPI.types.message.RawMessage import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MessageContent import com.github.insanusmokrassar.TelegramBotAPI.utils.toMarkdownText +import com.github.insanusmokrassar.TelegramBotAPI.utils.toMarkdownTexts data class TextContent( val text: String, @@ -29,4 +30,21 @@ data class TextContent( replyToMessageId, replyMarkup ) + + override fun createResends( + chatId: ChatIdentifier, + disableNotification: Boolean, + replyToMessageId: MessageIdentifier?, + replyMarkup: KeyboardMarkup? + ): List> = toMarkdownTexts().map { + SendMessage( + chatId, + it, + MarkdownParseMode, + false, + disableNotification, + replyToMessageId, + replyMarkup + ) + } } diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/message/content/abstracts/ResendableContent.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/message/content/abstracts/ResendableContent.kt index 0ad2ccf49d..2d53a39568 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/message/content/abstracts/ResendableContent.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/types/message/content/abstracts/ResendableContent.kt @@ -13,4 +13,11 @@ interface ResendableContent { replyToMessageId: MessageIdentifier? = null, replyMarkup: KeyboardMarkup? = null ): Request + + fun createResends( + chatId: ChatIdentifier, + disableNotification: Boolean = false, + replyToMessageId: MessageIdentifier? = null, + replyMarkup: KeyboardMarkup? = null + ): List> = listOf(createResend(chatId, disableNotification, replyToMessageId, replyMarkup)) } \ No newline at end of file diff --git a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/CaptionSourcer.kt b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/CaptionSourcer.kt index 45221f7716..0024ae2bdd 100644 --- a/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/CaptionSourcer.kt +++ b/src/main/kotlin/com/github/insanusmokrassar/TelegramBotAPI/utils/CaptionSourcer.kt @@ -1,39 +1,106 @@ package com.github.insanusmokrassar.TelegramBotAPI.utils import com.github.insanusmokrassar.TelegramBotAPI.types.MessageEntity.MessageEntity +import com.github.insanusmokrassar.TelegramBotAPI.types.MessageEntity.RegularTextMessageEntity +import com.github.insanusmokrassar.TelegramBotAPI.types.captionLength import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.TextContent import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.CaptionedMediaContent +import com.github.insanusmokrassar.TelegramBotAPI.types.textLength import com.github.insanusmokrassar.TelegramBotAPI.utils.extensions.toMarkdown +@Deprecated( + "Deprecated because old version have problem with long texts, but new one must return list of strings" +) fun createMarkdownText( text: String, messageEntities: List ): String { - val builder = StringBuilder() + return createMarkdownText( + convertToFullMessageEntityList(text, messageEntities) + ).first() +} + +fun createMarkdownText( + entities: List, + partLength: Int = 4096 +): List { + val texts = mutableListOf() + val textBuilder = StringBuilder(partLength) + for (entity in entities) { + val string = entity.asMarkdownSource + if (textBuilder.length + string.length > partLength) { + if (textBuilder.isNotEmpty()) { + texts.add(textBuilder.toString()) + textBuilder.clear() + } + val chunked = string.chunked(partLength) + val last = chunked.last() + textBuilder.append(last) + val listToAdd = if (chunked.size > 1) { + chunked.subList(0, chunked.size - 1) + } else { + emptyList() + } + listToAdd.forEach { + texts.add(it) + } + } else { + textBuilder.append(string) + } + } + if (textBuilder.isNotEmpty()) { + texts.add(textBuilder.toString()) + textBuilder.clear() + } + return texts +} + +@Deprecated( + "Deprecated because old version have problem with long texts, but new one must return list of strings" +) +fun CaptionedMediaContent.toMarkdownCaption(): String? = toMarkdownCaptions().firstOrNull() + +fun CaptionedMediaContent.toMarkdownCaptions(): List = createMarkdownText( + fullEntitiesList(), + captionLength.endInclusive + 1 +) + +fun CaptionedMediaContent.fullEntitiesList(): List = caption ?.let { + convertToFullMessageEntityList(it, captionEntities) +} ?: emptyList() + +@Deprecated( + "Deprecated because old version have problem with long texts, but new one must return list of strings" +) +fun TextContent.toMarkdownText(): String = toMarkdownTexts().first() + +fun TextContent.toMarkdownTexts(): List = createMarkdownText( + fullEntitiesList(), + textLength.endInclusive + 1 +) + +fun TextContent.fullEntitiesList(): List = convertToFullMessageEntityList(text, entities) + +fun convertToFullMessageEntityList( + text: String, + messageEntities: List +): List { + val result = mutableListOf() + var offset = 0 for (entity in messageEntities) { - builder.append( - text.substring(offset until entity.offset).toMarkdown() - ) - builder.append( - entity.asMarkdownSource - ) + val newEntitySize = entity.offset - offset + if (newEntitySize > 0) { + val regularEntity = RegularTextMessageEntity(offset, newEntitySize, text.substring(offset, entity.offset)) + result.add(regularEntity) + offset += regularEntity.length + } + result.add(entity) offset += entity.length } - builder.append( - text.substring(offset).toMarkdown() - ) - return builder.toString() + val newEntitySize = text.length - offset + if (newEntitySize > 0) { + result.add(RegularTextMessageEntity(offset, newEntitySize, text.substring(offset, text.length))) + } + return result } - -fun CaptionedMediaContent.toMarkdownCaption(): String? = caption ?.let { - createMarkdownText( - it, - captionEntities - ) -} - -fun TextContent.toMarkdownText(): String = createMarkdownText( - text, - entities -)