1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2025-11-19 13:55:57 +00:00

Compare commits

...

38 Commits

Author SHA1 Message Date
b0e32e8ad9 add opportunity to send emoji with sticker 2023-03-10 12:43:09 +06:00
79c9e6258f add setStickerMaskPosition 2023-03-10 12:28:16 +06:00
90b9c66bea rename all thumb* usages 2023-03-10 12:24:12 +06:00
e7b21dcd3d rename setStickerSetThumb to setStickerSetThumbnail 2023-03-10 12:11:17 +06:00
e30361ad1e rename thumb field 2023-03-10 12:02:40 +06:00
d8c659f866 add setStickerKeywords 2023-03-10 11:32:44 +06:00
5533303d86 add setStickerEmojiList 2023-03-10 11:28:21 +06:00
1633b9baaf add deleteStickerSet 2023-03-10 11:18:37 +06:00
a9725eb439 add support of setStickerSetTitle 2023-03-10 11:16:13 +06:00
a0aadef31b add support of localized bot description 2023-03-10 00:34:57 +06:00
ac88fd1d02 start 6.2.0 2023-03-10 00:23:16 +06:00
e3e318312d Merge pull request #734 from InsanusMokrassar/6.1.0
6.1.0
2023-03-08 17:10:47 +06:00
4c08fb7d26 small improvement in #732 solution 2023-03-08 16:41:10 +06:00
d83ff12560 update dependencies 2023-03-08 16:38:24 +06:00
818ef8481d fix of #732 2023-03-08 16:33:41 +06:00
f8cd446133 start 6.1.0 2023-03-08 16:24:31 +06:00
804b991921 update kdocs 2023-03-04 21:18:50 +06:00
817068aa71 Merge pull request #731 from InsanusMokrassar/renovate/dokka
Update dependency org.jetbrains.dokka:dokka-gradle-plugin to v1.8.10
2023-03-04 10:48:42 +06:00
renovate[bot]
0cca343612 Update dependency org.jetbrains.dokka:dokka-gradle-plugin to v1.8.10 2023-03-04 03:54:29 +00:00
6532bf255b Merge pull request #730 from InsanusMokrassar/6.0.3
6.0.3
2023-03-02 23:28:16 +06:00
421d5ae9e3 Update CHANGELOG.md 2023-03-02 21:59:58 +06:00
54f1181a14 Update libs.versions.toml 2023-03-02 21:59:26 +06:00
f616a02f7c hotfixes 2023-03-02 20:33:49 +06:00
f1deb93147 changes in InlineQuery 2023-03-02 19:33:15 +06:00
2300b44aae fix in CallbackQuery 2023-03-02 12:43:39 +06:00
fe88cf037a fixes in deeplinks 2023-03-02 08:32:06 +06:00
89920abe35 start 6.0.3 2023-03-02 08:31:35 +06:00
4c4aa491cb Merge pull request #729 from InsanusMokrassar/6.0.2
6.0.2
2023-03-01 15:33:43 +06:00
f0a4425be9 Update CHANGELOG.md 2023-03-01 15:31:34 +06:00
6c8af4cab3 fixes in media groups collecting and kdocs 2023-03-01 13:14:18 +06:00
017d57e5e5 fixes 2023-03-01 12:38:50 +06:00
5a456bcdbf add opportunity to collect media groups with debounce 2023-03-01 11:55:17 +06:00
4182d8f3fe start 6.0.2 2023-03-01 00:59:08 +06:00
c6e2cba09b Merge pull request #728 from InsanusMokrassar/6.0.1
6.0.1
2023-02-28 20:41:35 +06:00
8dd3eefd15 Update CHANGELOG.md 2023-02-28 19:59:23 +06:00
b72d4da8f0 Update libs.versions.toml 2023-02-28 19:57:11 +06:00
ebd023669d start 6.0.1 2023-02-28 19:55:29 +06:00
f7be4e557e Merge pull request #726 from InsanusMokrassar/6.0.0
6.0.0
2023-02-28 13:27:41 +06:00
98 changed files with 1055 additions and 279 deletions

View File

@@ -12,10 +12,10 @@ jobs:
with: with:
java-version: 11 java-version: 11
- name: Build - name: Build
run: ./gradlew dokkaHtml run: ./gradlew dokkaHtmlMultiModule
- name: Publish KDocs - name: Publish KDocs
uses: peaceiris/actions-gh-pages@v3 uses: peaceiris/actions-gh-pages@v3
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/build/dokka/html publish_dir: ./build/dokka/htmlMultiModule
publish_branch: kdocs publish_branch: kdocs

View File

@@ -1,5 +1,35 @@
# TelegramBotAPI changelog # TelegramBotAPI changelog
## 6.2.0
## 6.1.0
* `Versions`:
* `MicroUtils`: `0.17.2` -> `0.17.3`
* `API`:
* Fix of [#732](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/732)
## 6.0.3
* `Versions`:
* `MicroUtils`: `0.17.1` -> `0.17.2`
* `Core`:
* `User` in `CallbackQuery` now is `CommonUser` as well as in `from`
* `User` in `InlineQuery` now is `CommonUser` as well as in `from`
* `BehaviourBuilder`:
* Fixes in `DeepLink` triggers and waiters
## 6.0.2
* `Core`:
* Long polling now uses media groups debounce as in webhooks
## 6.0.1
* `Versions`:
* `Ktor`: `2.2.3` -> `2.2.4`
* `MicroUtils`: `0.17.0` -> `0.17.1`
## 6.0.0 ## 6.0.0
* `Versions`: * `Versions`:

View File

@@ -14,6 +14,10 @@ buildscript {
} }
} }
plugins {
alias(libs.plugins.kotlin.dokka)
}
// temporal crutch until legacy tests will be stabled or legacy target will be removed // temporal crutch until legacy tests will be stabled or legacy target will be removed
allprojects { allprojects {
repositories { repositories {

View File

@@ -6,4 +6,4 @@ kotlin.incremental=true
kotlin.incremental.js=true kotlin.incremental.js=true
library_group=dev.inmo library_group=dev.inmo
library_version=6.0.0 library_version=6.2.0

View File

@@ -8,15 +8,15 @@ javax-activation = "1.1.1"
korlibs = "3.4.0" korlibs = "3.4.0"
uuid = "0.7.0" uuid = "0.7.0"
ktor = "2.2.3" ktor = "2.2.4"
ksp = "1.8.10-1.0.9" ksp = "1.8.10-1.0.9"
kotlin-poet = "1.12.0" kotlin-poet = "1.12.0"
microutils = "0.17.0" microutils = "0.17.3"
github-release-plugin = "2.4.1" github-release-plugin = "2.4.1"
dokka = "1.7.20" dokka = "1.8.10"
[libraries] [libraries]
@@ -67,3 +67,4 @@ github-release-plugin = { module = "com.github.breadmoirai:github-release", vers
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
kotlin-dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }

View File

@@ -19,4 +19,3 @@ include ":tgbotapi.behaviour_builder"
include ":tgbotapi.behaviour_builder.fsm" include ":tgbotapi.behaviour_builder.fsm"
include ":tgbotapi" include ":tgbotapi"
include ":tgbotapi.webapps" include ":tgbotapi.webapps"
include ":docs"

View File

@@ -1,6 +1,7 @@
plugins { plugins {
id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization" id "org.jetbrains.kotlin.plugin.serialization"
id "org.jetbrains.dokka"
} }
project.description = "API extensions with \"Telegram Bot API\"-like extensions for TelegramBot and RequestsExecutor" project.description = "API extensions with \"Telegram Bot API\"-like extensions for TelegramBot and RequestsExecutor"

View File

@@ -5,7 +5,10 @@ import dev.inmo.tgbotapi.requests.DeleteMessage
import dev.inmo.tgbotapi.types.ChatIdentifier import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.MessageId import dev.inmo.tgbotapi.types.MessageId
import dev.inmo.tgbotapi.types.chat.Chat import dev.inmo.tgbotapi.types.chat.Chat
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.Message import dev.inmo.tgbotapi.types.message.abstracts.Message
import dev.inmo.tgbotapi.types.message.content.MediaGroupCollectionContent
import dev.inmo.tgbotapi.types.message.content.MediaGroupContent
suspend fun TelegramBot.deleteMessage( suspend fun TelegramBot.deleteMessage(
chatId: ChatIdentifier, chatId: ChatIdentifier,
@@ -21,7 +24,16 @@ suspend fun TelegramBot.deleteMessage(
suspend fun TelegramBot.deleteMessage( suspend fun TelegramBot.deleteMessage(
message: Message message: Message
) = deleteMessage(message.chat, message.messageId) ): Boolean {
val mediaGroupContent = ((message as? ContentMessage<*>) ?.content as? MediaGroupCollectionContent<*>)
if (mediaGroupContent == null) {
return deleteMessage(message.chat, message.messageId)
} else {
return mediaGroupContent.group.map {
deleteMessage(it.sourceMessage)
}.all { it }
}
}
suspend fun TelegramBot.delete( suspend fun TelegramBot.delete(
chatId: ChatIdentifier, chatId: ChatIdentifier,

View File

@@ -0,0 +1,16 @@
package dev.inmo.tgbotapi.extensions.api.bot
import dev.inmo.micro_utils.language_codes.IetfLanguageCode
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.bot.GetMyCommands
import dev.inmo.tgbotapi.requests.bot.GetMyDescription
import dev.inmo.tgbotapi.types.commands.BotCommandScope
import dev.inmo.tgbotapi.types.commands.BotCommandScopeDefault
suspend fun TelegramBot.getMyDescription(
languageCode: IetfLanguageCode? = null
) = execute(GetMyDescription(languageCode))
suspend fun TelegramBot.getMyDescription(
languageCode: String?
) = getMyDescription(languageCode ?.let(::IetfLanguageCode))

View File

@@ -0,0 +1,16 @@
package dev.inmo.tgbotapi.extensions.api.bot
import dev.inmo.micro_utils.language_codes.IetfLanguageCode
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.bot.GetMyCommands
import dev.inmo.tgbotapi.requests.bot.GetMyShortDescription
import dev.inmo.tgbotapi.types.commands.BotCommandScope
import dev.inmo.tgbotapi.types.commands.BotCommandScopeDefault
suspend fun TelegramBot.getMyShortDescription(
languageCode: IetfLanguageCode? = null
) = execute(GetMyShortDescription(languageCode))
suspend fun TelegramBot.getMyShortDescription(
languageCode: String?
) = getMyShortDescription(languageCode ?.let(::IetfLanguageCode))

View File

@@ -0,0 +1,19 @@
package dev.inmo.tgbotapi.extensions.api.bot
import dev.inmo.micro_utils.language_codes.IetfLanguageCode
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.bot.GetMyCommands
import dev.inmo.tgbotapi.requests.bot.GetMyDescription
import dev.inmo.tgbotapi.requests.bot.SetMyDescription
import dev.inmo.tgbotapi.types.commands.BotCommandScope
import dev.inmo.tgbotapi.types.commands.BotCommandScopeDefault
suspend fun TelegramBot.setMyDescription(
description: String? = null,
languageCode: IetfLanguageCode? = null
) = execute(SetMyDescription(description, languageCode))
suspend fun TelegramBot.setMyDescription(
description: String?,
languageCode: String?
) = setMyDescription(description, languageCode ?.let(::IetfLanguageCode))

View File

@@ -0,0 +1,15 @@
package dev.inmo.tgbotapi.extensions.api.bot
import dev.inmo.micro_utils.language_codes.IetfLanguageCode
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.bot.SetMyShortDescription
suspend fun TelegramBot.setMyShortDescription(
shortDescription: String? = null,
languageCode: IetfLanguageCode? = null
) = execute(SetMyShortDescription(shortDescription, languageCode))
suspend fun TelegramBot.setMyShortDescription(
shortDescription: String?,
languageCode: String?
) = setMyShortDescription(shortDescription, languageCode ?.let(::IetfLanguageCode))

View File

@@ -73,7 +73,7 @@ suspend fun TelegramBot.sendAnimation(
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
) = sendAnimation( ) = sendAnimation(
chatId, animation.fileId, animation.thumb ?.fileId, text, parseMode, spoilered, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup chatId, animation.fileId, animation.thumbnail ?.fileId, text, parseMode, spoilered, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup
) )
/** /**
@@ -177,7 +177,7 @@ suspend fun TelegramBot.sendAnimation(
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
) = sendAnimation( ) = sendAnimation(
chatId, animation.fileId, animation.thumb ?.fileId, entities, spoilered, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup chatId, animation.fileId, animation.thumbnail ?.fileId, entities, spoilered, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup
) )
/** /**

View File

@@ -88,7 +88,7 @@ suspend fun TelegramBot.sendAudio(
replyToMessageId: MessageId? = null, replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
) = sendAudio(chatId, audio.fileId, audio.thumb ?.fileId, text, parseMode, audio.duration, audio.performer, title, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup) ) = sendAudio(chatId, audio.fileId, audio.thumbnail ?.fileId, text, parseMode, audio.duration, audio.performer, title, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/** /**
* @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or * @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or
@@ -180,7 +180,7 @@ suspend inline fun TelegramBot.sendAudio(
replyToMessageId: MessageId? = null, replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
) = sendAudio(chatId, audio.fileId, audio.thumb ?.fileId, entities, audio.duration, audio.performer, title, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup) ) = sendAudio(chatId, audio.fileId, audio.thumbnail ?.fileId, entities, audio.duration, audio.performer, title, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/** /**
* @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or * @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or

View File

@@ -83,7 +83,7 @@ suspend fun TelegramBot.sendDocument(
replyMarkup: KeyboardMarkup? = null, replyMarkup: KeyboardMarkup? = null,
disableContentTypeDetection: Boolean? = null disableContentTypeDetection: Boolean? = null
) = sendDocument( ) = sendDocument(
chatId, document.fileId, document.thumb ?.fileId, text, parseMode, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup, disableContentTypeDetection chatId, document.fileId, document.thumbnail ?.fileId, text, parseMode, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup, disableContentTypeDetection
) )
/** /**
@@ -170,7 +170,7 @@ suspend inline fun TelegramBot.sendDocument(
replyMarkup: KeyboardMarkup? = null, replyMarkup: KeyboardMarkup? = null,
disableContentTypeDetection: Boolean? = null disableContentTypeDetection: Boolean? = null
) = sendDocument( ) = sendDocument(
chatId, document.fileId, document.thumb ?.fileId, entities, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup, disableContentTypeDetection chatId, document.fileId, document.thumbnail ?.fileId, entities, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup, disableContentTypeDetection
) )
/** /**

View File

@@ -70,7 +70,7 @@ suspend fun TelegramBot.sendVideo(
replyToMessageId: MessageId? = null, replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
) = sendVideo(chatId, video.fileId, video.thumb ?.fileId, text, parseMode, spoilered, video.duration, video.width, video.height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup) ) = sendVideo(chatId, video.fileId, video.thumbnail ?.fileId, text, parseMode, spoilered, video.duration, video.width, video.height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/** /**
* @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or * @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or
@@ -167,7 +167,7 @@ suspend inline fun TelegramBot.sendVideo(
replyToMessageId: MessageId? = null, replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
) = sendVideo(chatId, video.fileId, video.thumb ?.fileId, entities, spoilered, video.duration, video.width, video.height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup) ) = sendVideo(chatId, video.fileId, video.thumbnail ?.fileId, entities, spoilered, video.duration, video.width, video.height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/** /**
* @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or * @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or

View File

@@ -57,7 +57,7 @@ suspend fun TelegramBot.sendVideoNote(
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
) = sendVideoNote( ) = sendVideoNote(
chatId, videoNote.fileId, videoNote.thumb ?.fileId, videoNote.duration, videoNote.width, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup chatId, videoNote.fileId, videoNote.thumbnail ?.fileId, videoNote.duration, videoNote.width, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup
) )
/** /**

View File

@@ -0,0 +1,25 @@
package dev.inmo.tgbotapi.extensions.api.stickers
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.stickers.DeleteStickerFromSet
import dev.inmo.tgbotapi.requests.stickers.DeleteStickerSet
import dev.inmo.tgbotapi.types.StickerSetName
import dev.inmo.tgbotapi.types.files.Sticker
import dev.inmo.tgbotapi.types.stickers.StickerSet
suspend fun TelegramBot.deleteStickerSet(
name: StickerSetName
) = execute(
DeleteStickerSet(name)
)
suspend fun TelegramBot.deleteStickerSet(
sticker: Sticker
) = deleteStickerSet(
sticker.stickerSetName ?: error("Unable to take name of sticker set from sticker $sticker")
)
suspend fun TelegramBot.deleteStickerSet(
stickerSet: StickerSet,
) = deleteStickerSet(stickerSet.name)

View File

@@ -0,0 +1,25 @@
package dev.inmo.tgbotapi.extensions.api.stickers
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.stickers.SetStickerEmojiList
import dev.inmo.tgbotapi.requests.stickers.SetStickerPositionInSet
import dev.inmo.tgbotapi.types.files.Sticker
suspend fun TelegramBot.setStickerEmojiList(
sticker: FileId,
emojis: List<String>
) = execute(
SetStickerEmojiList(
sticker,
emojis
)
)
suspend fun TelegramBot.setStickerEmojiList(
sticker: Sticker,
vararg emojis: String
) = setStickerEmojiList(
sticker.fileId,
emojis.toList()
)

View File

@@ -0,0 +1,26 @@
package dev.inmo.tgbotapi.extensions.api.stickers
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.stickers.SetStickerEmojiList
import dev.inmo.tgbotapi.requests.stickers.SetStickerKeywords
import dev.inmo.tgbotapi.requests.stickers.SetStickerPositionInSet
import dev.inmo.tgbotapi.types.files.Sticker
suspend fun TelegramBot.setStickerKeywords(
sticker: FileId,
keywords: List<String>
) = execute(
SetStickerKeywords(
sticker,
keywords
)
)
suspend fun TelegramBot.setStickerKeywords(
sticker: Sticker,
vararg keywords: String
) = setStickerKeywords(
sticker.fileId,
keywords.toList()
)

View File

@@ -0,0 +1,19 @@
package dev.inmo.tgbotapi.extensions.api.stickers
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.stickers.SetStickerEmojiList
import dev.inmo.tgbotapi.requests.stickers.SetStickerMaskPosition
import dev.inmo.tgbotapi.requests.stickers.SetStickerPositionInSet
import dev.inmo.tgbotapi.types.files.Sticker
import dev.inmo.tgbotapi.types.stickers.MaskPosition
suspend fun TelegramBot.setStickerMaskPosition(
sticker: FileId,
maskPosition: MaskPosition
) = execute(
SetStickerMaskPosition(
sticker,
maskPosition
)
)

View File

@@ -3,27 +3,95 @@ package dev.inmo.tgbotapi.extensions.api.thumbs
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.abstracts.FileId import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
import dev.inmo.tgbotapi.requests.stickers.SetStickerSetThumb import dev.inmo.tgbotapi.requests.stickers.SetStickerSetThumbnail
import dev.inmo.tgbotapi.types.StickerSetName
import dev.inmo.tgbotapi.types.chat.CommonUser import dev.inmo.tgbotapi.types.chat.CommonUser
import dev.inmo.tgbotapi.types.UserId import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.stickers.StickerSet import dev.inmo.tgbotapi.types.stickers.StickerSet
suspend fun TelegramBot.setStickerSetThumbnail(
userId: UserId,
stickerSetName: StickerSetName,
thumbnail: FileId
) = execute(
SetStickerSetThumbnail(userId, stickerSetName, thumbnail)
)
suspend fun TelegramBot.setStickerSetThumbnail(
userId: UserId,
stickerSetName: StickerSetName,
thumbnail: MultipartFile
) = execute(
SetStickerSetThumbnail(userId, stickerSetName, thumbnail)
)
suspend fun TelegramBot.setStickerSetThumbnail(
user: CommonUser,
stickerSetName: StickerSetName,
thumbnail: FileId
) = setStickerSetThumbnail(
user.id, stickerSetName, thumbnail
)
suspend fun TelegramBot.setStickerSetThumbnail(
user: CommonUser,
stickerSetName: StickerSetName,
thumbnail: MultipartFile
) = setStickerSetThumbnail(
user.id, stickerSetName, thumbnail
)
suspend fun TelegramBot.setStickerSetThumbnail(
userId: UserId,
stickerSet: StickerSet,
thumbnail: FileId
) = setStickerSetThumbnail(
userId, stickerSet.name, thumbnail
)
suspend fun TelegramBot.setStickerSetThumbnail(
userId: UserId,
stickerSet: StickerSet,
thumbnail: MultipartFile
) = setStickerSetThumbnail(
userId, stickerSet.name, thumbnail
)
suspend fun TelegramBot.setStickerSetThumbnail(
user: CommonUser,
stickerSet: StickerSet,
thumbnail: FileId
) = setStickerSetThumbnail(
user.id, stickerSet.name, thumbnail
)
suspend fun TelegramBot.setStickerSetThumbnail(
user: CommonUser,
stickerSet: StickerSet,
thumbnail: MultipartFile
) = setStickerSetThumbnail(
user.id, stickerSet.name, thumbnail
)
@Deprecated("Renamed in telegram bot api", ReplaceWith("setStickerSetThumbnail(userId, thumbSetName, thumb)", "dev.inmo.tgbotapi.extensions.api.thumbs.setStickerSetThumbnail"))
suspend fun TelegramBot.setStickerSetThumb( suspend fun TelegramBot.setStickerSetThumb(
userId: UserId, userId: UserId,
thumbSetName: String, thumbSetName: String,
thumb: FileId thumb: FileId
) = execute( ) = execute(
SetStickerSetThumb(userId, thumbSetName, thumb) SetStickerSetThumbnail(userId, thumbSetName, thumb)
) )
@Deprecated("Renamed in telegram bot api", ReplaceWith("setStickerSetThumbnail(userId, thumbSetName, thumb)", "dev.inmo.tgbotapi.extensions.api.thumbs.setStickerSetThumbnail"))
suspend fun TelegramBot.setStickerSetThumb( suspend fun TelegramBot.setStickerSetThumb(
userId: UserId, userId: UserId,
thumbSetName: String, thumbSetName: String,
thumb: MultipartFile thumb: MultipartFile
) = execute( ) = execute(
SetStickerSetThumb(userId, thumbSetName, thumb) SetStickerSetThumbnail(userId, thumbSetName, thumb)
) )
@Deprecated("Renamed in telegram bot api", ReplaceWith("setStickerSetThumbnail(user, thumbSetName, thumb)", "dev.inmo.tgbotapi.extensions.api.thumbs.setStickerSetThumbnail"))
suspend fun TelegramBot.setStickerSetThumb( suspend fun TelegramBot.setStickerSetThumb(
user: CommonUser, user: CommonUser,
thumbSetName: String, thumbSetName: String,
@@ -32,6 +100,7 @@ suspend fun TelegramBot.setStickerSetThumb(
user.id, thumbSetName, thumb user.id, thumbSetName, thumb
) )
@Deprecated("Renamed in telegram bot api", ReplaceWith("setStickerSetThumbnail(user, thumbSetName, thumb)", "dev.inmo.tgbotapi.extensions.api.thumbs.setStickerSetThumbnail"))
suspend fun TelegramBot.setStickerSetThumb( suspend fun TelegramBot.setStickerSetThumb(
user: CommonUser, user: CommonUser,
thumbSetName: String, thumbSetName: String,
@@ -40,6 +109,7 @@ suspend fun TelegramBot.setStickerSetThumb(
user.id, thumbSetName, thumb user.id, thumbSetName, thumb
) )
@Deprecated("Renamed in telegram bot api", ReplaceWith("setStickerSetThumbnail(userId, thumbSet, thumb)", "dev.inmo.tgbotapi.extensions.api.thumbs.setStickerSetThumbnail"))
suspend fun TelegramBot.setStickerSetThumb( suspend fun TelegramBot.setStickerSetThumb(
userId: UserId, userId: UserId,
thumbSet: StickerSet, thumbSet: StickerSet,
@@ -48,6 +118,7 @@ suspend fun TelegramBot.setStickerSetThumb(
userId, thumbSet.name, thumb userId, thumbSet.name, thumb
) )
@Deprecated("Renamed in telegram bot api", ReplaceWith("setStickerSetThumbnail(userId, thumbSet, thumb)", "dev.inmo.tgbotapi.extensions.api.thumbs.setStickerSetThumbnail"))
suspend fun TelegramBot.setStickerSetThumb( suspend fun TelegramBot.setStickerSetThumb(
userId: UserId, userId: UserId,
thumbSet: StickerSet, thumbSet: StickerSet,
@@ -56,6 +127,7 @@ suspend fun TelegramBot.setStickerSetThumb(
userId, thumbSet.name, thumb userId, thumbSet.name, thumb
) )
@Deprecated("Renamed in telegram bot api", ReplaceWith("setStickerSetThumbnail(user, thumbSet, thumb)", "dev.inmo.tgbotapi.extensions.api.thumbs.setStickerSetThumbnail"))
suspend fun TelegramBot.setStickerSetThumb( suspend fun TelegramBot.setStickerSetThumb(
user: CommonUser, user: CommonUser,
thumbSet: StickerSet, thumbSet: StickerSet,
@@ -64,6 +136,7 @@ suspend fun TelegramBot.setStickerSetThumb(
user.id, thumbSet.name, thumb user.id, thumbSet.name, thumb
) )
@Deprecated("Renamed in telegram bot api", ReplaceWith("setStickerSetThumbnail(user, thumbSet, thumb)", "dev.inmo.tgbotapi.extensions.api.thumbs.setStickerSetThumbnail"))
suspend fun TelegramBot.setStickerSetThumb( suspend fun TelegramBot.setStickerSetThumb(
user: CommonUser, user: CommonUser,
thumbSet: StickerSet, thumbSet: StickerSet,

View File

@@ -0,0 +1,22 @@
package dev.inmo.tgbotapi.extensions.api.stickers
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.stickers.SetStickerSetTitle
import dev.inmo.tgbotapi.types.StickerSetName
import dev.inmo.tgbotapi.types.files.Sticker
import dev.inmo.tgbotapi.types.stickers.StickerSet
suspend fun TelegramBot.setStickerSetTitle(
name: StickerSetName,
title: String
) = execute(SetStickerSetTitle(name, title))
suspend fun TelegramBot.setStickerSetTitle(
sticker: Sticker,
title: String
) = setStickerSetTitle(sticker.stickerSetName ?: error("Unable to take name of sticker set from sticker $sticker"), title)
suspend fun TelegramBot.setStickerSetTitle(
stickerSet: StickerSet,
title: String
) = setStickerSetTitle(stickerSet.name, title)

View File

@@ -1,7 +1,8 @@
package dev.inmo.tgbotapi.extensions.api.utils package dev.inmo.tgbotapi.extensions.api.utils
import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions
import dev.inmo.tgbotapi.extensions.api.InternalUtils.convertWithMediaGroupUpdates import dev.inmo.tgbotapi.extensions.api.InternalUtils.convertWithMediaGroupUpdates
import dev.inmo.tgbotapi.types.message.abstracts.PossiblySentViaBotCommonMessage import dev.inmo.tgbotapi.types.message.abstracts.PossiblyMediaGroupMessage
import dev.inmo.tgbotapi.types.update.abstracts.BaseMessageUpdate import dev.inmo.tgbotapi.types.update.abstracts.BaseMessageUpdate
import dev.inmo.tgbotapi.types.update.abstracts.Update import dev.inmo.tgbotapi.types.update.abstracts.Update
import dev.inmo.tgbotapi.updateshandlers.UpdateReceiver import dev.inmo.tgbotapi.updateshandlers.UpdateReceiver
@@ -28,26 +29,18 @@ fun CoroutineScope.updateHandlerWithMediaGroupsAdaptation(
) )
launch { launch {
launch { launchSafelyWithoutExceptions {
for (update in updatesChannel) { for (update in updatesChannel) {
val dataAsPossiblySentViaBotCommonMessage = update.data as? PossiblySentViaBotCommonMessage<*> val data = update.data
when {
if (dataAsPossiblySentViaBotCommonMessage == null) { data is PossiblyMediaGroupMessage<*> && data.mediaGroupId != null -> {
output(update) mediaGroupChannel.send("${data.mediaGroupId}${update::class.simpleName}" to update as BaseMessageUpdate)
continue }
else -> output(update)
} }
val mediaGroupId = dataAsPossiblySentViaBotCommonMessage.mediaGroupId
if (mediaGroupId == null) {
output(update)
continue
}
mediaGroupChannel.send("${mediaGroupId}${update::class.simpleName}" to update as BaseMessageUpdate)
} }
} }
launch { launchSafelyWithoutExceptions {
for ((_, mediaGroup) in mediaGroupAccumulatedChannel) { for ((_, mediaGroup) in mediaGroupAccumulatedChannel) {
mediaGroup.convertWithMediaGroupUpdates().forEach { mediaGroup.convertWithMediaGroupUpdates().forEach {
output(it) output(it)

View File

@@ -1,6 +1,7 @@
plugins { plugins {
id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization" id "org.jetbrains.kotlin.plugin.serialization"
id "org.jetbrains.dokka"
} }
project.description = "Behaviour Builder DSL" project.description = "Behaviour Builder DSL"

View File

@@ -8,6 +8,7 @@ import dev.inmo.micro_utils.fsm.common.utils.StateHandlingErrorHandler
import dev.inmo.micro_utils.fsm.common.utils.defaultStateHandlingErrorHandler import dev.inmo.micro_utils.fsm.common.utils.defaultStateHandlingErrorHandler
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.longPolling import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.longPolling
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.updateHandlerWithMediaGroupsAdaptation
import dev.inmo.tgbotapi.types.Seconds import dev.inmo.tgbotapi.types.Seconds
import dev.inmo.tgbotapi.types.update.abstracts.Update import dev.inmo.tgbotapi.types.update.abstracts.Update
import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
@@ -47,6 +48,10 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSM(
* Use [buildBehaviourWithFSM] to create [BehaviourContextWithFSM] and launch getting of updates * Use [buildBehaviourWithFSM] to create [BehaviourContextWithFSM] and launch getting of updates
* using [longPolling]. For [longPolling] will be used result [BehaviourContextWithFSM] for both parameters * using [longPolling]. For [longPolling] will be used result [BehaviourContextWithFSM] for both parameters
* flowsUpdatesFilter and scope * flowsUpdatesFilter and scope
*
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
* retrieved in different updates
*/ */
suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling( suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
upstreamUpdatesFlow: Flow<Update>? = null, upstreamUpdatesFlow: Flow<Update>? = null,
@@ -58,6 +63,7 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
timeoutSeconds: Seconds = 30, timeoutSeconds: Seconds = 30,
autoDisableWebhooks: Boolean = true, autoDisableWebhooks: Boolean = true,
autoSkipTimeoutExceptions: Boolean = true, autoSkipTimeoutExceptions: Boolean = true,
mediaGroupsDebounceTimeMillis: Long? = 1000L,
block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit> block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit>
): Pair<DefaultBehaviourContextWithFSM<T>, Job> = buildBehaviourWithFSM( ): Pair<DefaultBehaviourContextWithFSM<T>, Job> = buildBehaviourWithFSM(
upstreamUpdatesFlow, upstreamUpdatesFlow,
@@ -70,7 +76,7 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
).run { ).run {
this to scope.launch { this to scope.launch {
start() start()
longPolling(flowsUpdatesFilter, timeoutSeconds, scope, autoDisableWebhooks, autoSkipTimeoutExceptions, defaultExceptionsHandler) longPolling(flowsUpdatesFilter, timeoutSeconds, scope, autoDisableWebhooks, autoSkipTimeoutExceptions, mediaGroupsDebounceTimeMillis, defaultExceptionsHandler)
} }
} }
@@ -116,6 +122,10 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSM(
* using [longPolling]. For [longPolling] will be used result [BehaviourContextWithFSM] for both parameters * using [longPolling]. For [longPolling] will be used result [BehaviourContextWithFSM] for both parameters
* flowsUpdatesFilter and scope * flowsUpdatesFilter and scope
* *
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
* retrieved in different updates
*
* @see buildBehaviourWithFSMAndStartLongPolling * @see buildBehaviourWithFSMAndStartLongPolling
* @see BehaviourContext * @see BehaviourContext
* @see longPolling * @see longPolling
@@ -131,6 +141,7 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
timeoutSeconds: Seconds = 30, timeoutSeconds: Seconds = 30,
autoDisableWebhooks: Boolean = true, autoDisableWebhooks: Boolean = true,
autoSkipTimeoutExceptions: Boolean = true, autoSkipTimeoutExceptions: Boolean = true,
mediaGroupsDebounceTimeMillis: Long? = 1000L,
block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit> block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit>
) = FlowsUpdatesFilter().let { ) = FlowsUpdatesFilter().let {
buildBehaviourWithFSM( buildBehaviourWithFSM(
@@ -149,6 +160,7 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
scope, scope,
autoDisableWebhooks, autoDisableWebhooks,
autoSkipTimeoutExceptions, autoSkipTimeoutExceptions,
mediaGroupsDebounceTimeMillis,
defaultExceptionsHandler defaultExceptionsHandler
) )
} }

View File

@@ -11,6 +11,7 @@ import dev.inmo.tgbotapi.bot.ktor.KtorRequestsExecutorBuilder
import dev.inmo.tgbotapi.bot.ktor.telegramBot import dev.inmo.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.startGettingOfUpdatesByLongPolling import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.startGettingOfUpdatesByLongPolling
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.updateHandlerWithMediaGroupsAdaptation
import dev.inmo.tgbotapi.types.Seconds import dev.inmo.tgbotapi.types.Seconds
import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl
@@ -26,6 +27,10 @@ import kotlin.coroutines.coroutineContext
* **WARNING** This method WILL NOT launch any listening of updates. Use something like * **WARNING** This method WILL NOT launch any listening of updates. Use something like
* [startGettingOfUpdatesByLongPolling] or tools for work with webhooks * [startGettingOfUpdatesByLongPolling] or tools for work with webhooks
* *
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
* retrieved in different updates
*
* @return Created bot which has been used to create [BehaviourContext] via [buildBehaviourWithFSM] * @return Created bot which has been used to create [BehaviourContext] via [buildBehaviourWithFSM]
* *
* @see [BehaviourContext] * @see [BehaviourContext]
@@ -46,6 +51,7 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSM(
timeoutSeconds: Seconds = 30, timeoutSeconds: Seconds = 30,
autoDisableWebhooks: Boolean = true, autoDisableWebhooks: Boolean = true,
autoSkipTimeoutExceptions: Boolean = true, autoSkipTimeoutExceptions: Boolean = true,
mediaGroupsDebounceTimeMillis: Long? = 1000L,
block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit> block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit>
): TelegramBot = telegramBot( ): TelegramBot = telegramBot(
token, token,
@@ -63,6 +69,7 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSM(
timeoutSeconds, timeoutSeconds,
autoDisableWebhooks, autoDisableWebhooks,
autoSkipTimeoutExceptions, autoSkipTimeoutExceptions,
mediaGroupsDebounceTimeMillis,
block block
) )
} }
@@ -71,6 +78,10 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSM(
* Create bot using [telegramBot] and start listening for updates using [buildBehaviourWithFSMAndStartLongPolling]. This * Create bot using [telegramBot] and start listening for updates using [buildBehaviourWithFSMAndStartLongPolling]. This
* method will launch updates retrieving via long polling inside of [buildBehaviourWithFSMAndStartLongPolling] * method will launch updates retrieving via long polling inside of [buildBehaviourWithFSMAndStartLongPolling]
* *
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
* retrieved in different updates
*
* @return Pair of [TelegramBot] and [Job]. This [Job] can be used to stop listening updates in your [block] you passed * @return Pair of [TelegramBot] and [Job]. This [Job] can be used to stop listening updates in your [block] you passed
* here * here
* *
@@ -91,6 +102,7 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSMAndStartLongPolling(
timeoutSeconds: Seconds = 30, timeoutSeconds: Seconds = 30,
autoDisableWebhooks: Boolean = true, autoDisableWebhooks: Boolean = true,
autoSkipTimeoutExceptions: Boolean = true, autoSkipTimeoutExceptions: Boolean = true,
mediaGroupsDebounceTimeMillis: Long? = 1000L,
block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit> block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit>
): Pair<TelegramBot, Job> { ): Pair<TelegramBot, Job> {
return telegramBot( return telegramBot(
@@ -108,6 +120,7 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSMAndStartLongPolling(
timeoutSeconds, timeoutSeconds,
autoDisableWebhooks, autoDisableWebhooks,
autoSkipTimeoutExceptions, autoSkipTimeoutExceptions,
mediaGroupsDebounceTimeMillis,
block block
) )
} }

View File

@@ -1,6 +1,7 @@
plugins { plugins {
id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization" id "org.jetbrains.kotlin.plugin.serialization"
id "org.jetbrains.dokka"
} }
project.description = "Behaviour Builder DSL" project.description = "Behaviour Builder DSL"

View File

@@ -5,6 +5,7 @@ import dev.inmo.micro_utils.coroutines.ExceptionHandler
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.longPolling import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.longPolling
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.startGettingOfUpdatesByLongPolling import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.startGettingOfUpdatesByLongPolling
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.updateHandlerWithMediaGroupsAdaptation
import dev.inmo.tgbotapi.types.Seconds import dev.inmo.tgbotapi.types.Seconds
import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
import kotlinx.coroutines.* import kotlinx.coroutines.*
@@ -47,6 +48,10 @@ suspend fun TelegramBot.buildBehaviour(
* Use this method to build bot behaviour and run it via long polling. In case you wish to get [FlowsUpdatesFilter] for * Use this method to build bot behaviour and run it via long polling. In case you wish to get [FlowsUpdatesFilter] for
* additional manipulations, you must provide external [FlowsUpdatesFilter] in other [buildBehaviour] function. * additional manipulations, you must provide external [FlowsUpdatesFilter] in other [buildBehaviour] function.
* *
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
* retrieved in different updates
*
* @see buildBehaviour * @see buildBehaviour
* @see BehaviourContext * @see BehaviourContext
* @see startGettingOfUpdatesByLongPolling * @see startGettingOfUpdatesByLongPolling
@@ -57,6 +62,7 @@ suspend fun TelegramBot.buildBehaviourWithLongPolling(
timeoutSeconds: Seconds = 30, timeoutSeconds: Seconds = 30,
autoDisableWebhooks: Boolean = true, autoDisableWebhooks: Boolean = true,
autoSkipTimeoutExceptions: Boolean = true, autoSkipTimeoutExceptions: Boolean = true,
mediaGroupsDebounceTimeMillis: Long? = 1000L,
block: BehaviourContextReceiver<Unit> block: BehaviourContextReceiver<Unit>
): Job { ): Job {
val behaviourContext = buildBehaviour( val behaviourContext = buildBehaviour(
@@ -69,6 +75,7 @@ suspend fun TelegramBot.buildBehaviourWithLongPolling(
scope = behaviourContext, scope = behaviourContext,
timeoutSeconds = timeoutSeconds, timeoutSeconds = timeoutSeconds,
autoDisableWebhooks = autoDisableWebhooks, autoDisableWebhooks = autoDisableWebhooks,
autoSkipTimeoutExceptions = autoSkipTimeoutExceptions autoSkipTimeoutExceptions = autoSkipTimeoutExceptions,
mediaGroupsDebounceTimeMillis = mediaGroupsDebounceTimeMillis
) )
} }

View File

@@ -5,6 +5,7 @@ import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.bot.ktor.KtorRequestsExecutorBuilder import dev.inmo.tgbotapi.bot.ktor.KtorRequestsExecutorBuilder
import dev.inmo.tgbotapi.bot.ktor.telegramBot import dev.inmo.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.startGettingOfUpdatesByLongPolling import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.startGettingOfUpdatesByLongPolling
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.updateHandlerWithMediaGroupsAdaptation
import dev.inmo.tgbotapi.types.Seconds import dev.inmo.tgbotapi.types.Seconds
import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl
@@ -53,6 +54,10 @@ suspend fun telegramBotWithBehaviour(
* *
* **WARNING** This method WILL launch updates listening inside of calling [buildBehaviourWithLongPolling] * **WARNING** This method WILL launch updates listening inside of calling [buildBehaviourWithLongPolling]
* *
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
* retrieved in different updates
*
* @return Pair of [TelegramBot] and [Job]. This [Job] can be used to stop listening updates in your [block] you passed * @return Pair of [TelegramBot] and [Job]. This [Job] can be used to stop listening updates in your [block] you passed
* here * here
* *
@@ -70,6 +75,7 @@ suspend fun telegramBotWithBehaviourAndLongPolling(
timeoutSeconds: Seconds = 30, timeoutSeconds: Seconds = 30,
autoDisableWebhooks: Boolean = true, autoDisableWebhooks: Boolean = true,
autoSkipTimeoutExceptions: Boolean = true, autoSkipTimeoutExceptions: Boolean = true,
mediaGroupsDebounceTimeMillis: Long? = 1000L,
block: BehaviourContextReceiver<Unit> block: BehaviourContextReceiver<Unit>
): Pair<TelegramBot, Job> { ): Pair<TelegramBot, Job> {
return telegramBot( return telegramBot(
@@ -84,6 +90,7 @@ suspend fun telegramBotWithBehaviourAndLongPolling(
timeoutSeconds, timeoutSeconds,
autoDisableWebhooks, autoDisableWebhooks,
autoSkipTimeoutExceptions, autoSkipTimeoutExceptions,
mediaGroupsDebounceTimeMillis,
block block
) )
} }

View File

@@ -38,7 +38,7 @@ suspend fun <BC : BehaviourContext> BC.onDeepLink(
scenarioReceiver, scenarioReceiver,
) { ) {
(it.messageUpdateOrNull()) ?.data ?.commonMessageOrNull() ?.withContentOrNull<TextContent>() ?.let { message -> (it.messageUpdateOrNull()) ?.data ?.commonMessageOrNull() ?.withContentOrNull<TextContent>() ?.let { message ->
message to message.content.textSources[1].source.removePrefix(" ").decodeURLQueryComponent() message to (message.content.textSources.getOrNull(1) ?.source ?.removePrefix(" ") ?.decodeURLQueryComponent() ?: return@let null)
} ?.let(::listOfNotNull) } ?.let(::listOfNotNull)
}.also { }.also {
triggersHolder.handleableCommandsHolder.registerHandleable(startRegex) triggersHolder.handleableCommandsHolder.registerHandleable(startRegex)

View File

@@ -2,6 +2,7 @@ plugins {
id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization" id "org.jetbrains.kotlin.plugin.serialization"
id "com.google.devtools.ksp" id "com.google.devtools.ksp"
id "org.jetbrains.dokka"
} }
project.description = "Core part of tgbotapi with all (and only) required functionality for working with Telegram Bot API" project.description = "Core part of tgbotapi with all (and only) required functionality for working with Telegram Bot API"

View File

@@ -0,0 +1,23 @@
package dev.inmo.tgbotapi.requests.bot
import dev.inmo.micro_utils.language_codes.IetfLanguageCode
import dev.inmo.micro_utils.language_codes.IetfLanguageCodeSerializer
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.abstracts.WithOptionalLanguageCode
import dev.inmo.tgbotapi.types.commands.*
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
@Serializable
class GetMyDescription(
@SerialName(languageCodeField)
@Serializable(IetfLanguageCodeSerializer::class)
override val ietfLanguageCode: IetfLanguageCode? = null
) : SimpleRequest<BotDescription>, WithOptionalLanguageCode {
override fun method(): String = "getMyDescription"
override val resultDeserializer: DeserializationStrategy<BotDescription>
get() = BotDescription.serializer()
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -0,0 +1,23 @@
package dev.inmo.tgbotapi.requests.bot
import dev.inmo.micro_utils.language_codes.IetfLanguageCode
import dev.inmo.micro_utils.language_codes.IetfLanguageCodeSerializer
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.abstracts.WithOptionalLanguageCode
import dev.inmo.tgbotapi.types.commands.*
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
@Serializable
class GetMyShortDescription(
@SerialName(languageCodeField)
@Serializable(IetfLanguageCodeSerializer::class)
override val ietfLanguageCode: IetfLanguageCode? = null
) : SimpleRequest<BotShortDescription>, WithOptionalLanguageCode {
override fun method(): String = "getMyShortDescription"
override val resultDeserializer: DeserializationStrategy<BotShortDescription>
get() = BotShortDescription.serializer()
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -0,0 +1,25 @@
package dev.inmo.tgbotapi.requests.bot
import dev.inmo.micro_utils.language_codes.IetfLanguageCode
import dev.inmo.micro_utils.language_codes.IetfLanguageCodeSerializer
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.abstracts.WithOptionalLanguageCode
import dev.inmo.tgbotapi.types.commands.*
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
@Serializable
class SetMyDescription(
@SerialName(descriptionField)
val description: String? = null,
@SerialName(languageCodeField)
@Serializable(IetfLanguageCodeSerializer::class)
override val ietfLanguageCode: IetfLanguageCode? = null
) : SimpleRequest<Boolean>, WithOptionalLanguageCode {
override fun method(): String = "setMyDescription"
override val resultDeserializer: DeserializationStrategy<Boolean>
get() = Boolean.serializer()
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -0,0 +1,25 @@
package dev.inmo.tgbotapi.requests.bot
import dev.inmo.micro_utils.language_codes.IetfLanguageCode
import dev.inmo.micro_utils.language_codes.IetfLanguageCodeSerializer
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.abstracts.WithOptionalLanguageCode
import dev.inmo.tgbotapi.types.commands.*
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
@Serializable
class SetMyShortDescription(
@SerialName(shortDescriptionField)
val shortDescription: String? = null,
@SerialName(languageCodeField)
@Serializable(IetfLanguageCodeSerializer::class)
override val ietfLanguageCode: IetfLanguageCode? = null
) : SimpleRequest<Boolean>, WithOptionalLanguageCode {
override fun method(): String = "setMyShortDescription"
override val resultDeserializer: DeserializationStrategy<Boolean>
get() = Boolean.serializer()
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -1,5 +1,9 @@
package dev.inmo.tgbotapi.requests.send.abstracts package dev.inmo.tgbotapi.requests.send.abstracts
interface ThumbedSendMessageRequest<T: Any>: SendMessageRequest<T> { interface ThumbedSendMessageRequest<T: Any>: SendMessageRequest<T> {
val thumbnail: String?
@Deprecated("Renamed in telegram bot api", ReplaceWith("thumbnail"))
val thumb: String? val thumb: String?
} get() = thumbnail
}

View File

@@ -129,8 +129,8 @@ data class SendAnimationData internal constructor(
override val chatId: ChatIdentifier, override val chatId: ChatIdentifier,
@SerialName(animationField) @SerialName(animationField)
val animation: String? = null, val animation: String? = null,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: String? = null, override val thumbnail: String? = null,
@SerialName(captionField) @SerialName(captionField)
override val text: String? = null, override val text: String? = null,
@SerialName(parseModeField) @SerialName(parseModeField)
@@ -187,8 +187,8 @@ data class SendAnimationData internal constructor(
data class SendAnimationFiles internal constructor( data class SendAnimationFiles internal constructor(
val animation: MultipartFile? = null, val animation: MultipartFile? = null,
val thumb: MultipartFile? = null val thumbnail: MultipartFile? = null
) : Files by mapOfNotNull( ) : Files by mapOfNotNull(
animationField to animation, animationField to animation,
thumbField to thumb thumbnailField to thumbnail
) )

View File

@@ -126,8 +126,8 @@ data class SendAudioData internal constructor(
override val chatId: ChatIdentifier, override val chatId: ChatIdentifier,
@SerialName(audioField) @SerialName(audioField)
val audio: String? = null, val audio: String? = null,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: String? = null, override val thumbnail: String? = null,
@SerialName(captionField) @SerialName(captionField)
override val text: String? = null, override val text: String? = null,
@SerialName(parseModeField) @SerialName(parseModeField)
@@ -182,8 +182,8 @@ data class SendAudioData internal constructor(
data class SendAudioFiles internal constructor( data class SendAudioFiles internal constructor(
val audio: MultipartFile? = null, val audio: MultipartFile? = null,
val thumb: MultipartFile? = null val thumbnail: MultipartFile? = null
) : Files by mapOfNotNull( ) : Files by mapOfNotNull(
audioField to audio, audioField to audio,
thumbField to thumb thumbnailField to thumbnail
) )

View File

@@ -144,8 +144,8 @@ data class SendDocumentData internal constructor(
override val chatId: ChatIdentifier, override val chatId: ChatIdentifier,
@SerialName(documentField) @SerialName(documentField)
val document: String? = null, val document: String? = null,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: String? = null, override val thumbnail: String? = null,
@SerialName(captionField) @SerialName(captionField)
override val text: String? = null, override val text: String? = null,
@SerialName(parseModeField) @SerialName(parseModeField)
@@ -193,8 +193,8 @@ data class SendDocumentData internal constructor(
data class SendDocumentFiles internal constructor( data class SendDocumentFiles internal constructor(
val document: MultipartFile? = null, val document: MultipartFile? = null,
val thumb: MultipartFile? = null val thumbnail: MultipartFile? = null
) : Files by mapOfNotNull( ) : Files by mapOfNotNull(
documentField to document, documentField to document,
thumbField to thumb thumbnailField to thumbnail
) )

View File

@@ -8,14 +8,19 @@ import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import dev.inmo.tgbotapi.types.message.content.StickerContent import dev.inmo.tgbotapi.types.message.content.StickerContent
import dev.inmo.tgbotapi.utils.mapOfNotNull
import dev.inmo.tgbotapi.utils.toJsonWithoutNulls import dev.inmo.tgbotapi.utils.toJsonWithoutNulls
import kotlinx.serialization.* import kotlinx.serialization.*
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put
fun SendSticker( fun SendSticker(
chatId: ChatIdentifier, chatId: ChatIdentifier,
sticker: InputFile, sticker: InputFile,
threadId: MessageThreadId? = chatId.threadId, threadId: MessageThreadId? = chatId.threadId,
emoji: String? = null,
disableNotification: Boolean = false, disableNotification: Boolean = false,
protectContent: Boolean = false, protectContent: Boolean = false,
replyToMessageId: MessageId? = null, replyToMessageId: MessageId? = null,
@@ -32,7 +37,7 @@ fun SendSticker(
replyMarkup replyMarkup
).let { ).let {
when (sticker) { when (sticker) {
is MultipartFile -> SendStickerByFile(it, sticker) is MultipartFile -> SendStickerByFile(it, sticker, emoji)
is FileId -> it is FileId -> it
} }
} }
@@ -69,8 +74,16 @@ data class SendStickerByFileId internal constructor(
data class SendStickerByFile internal constructor( data class SendStickerByFile internal constructor(
@Transient @Transient
private val sendStickerByFileId: SendStickerByFileId, private val sendStickerByFileId: SendStickerByFileId,
val sticker: MultipartFile val sticker: MultipartFile,
val emoji: String?
) : MultipartRequest<ContentMessage<StickerContent>>, Request<ContentMessage<StickerContent>> by sendStickerByFileId { ) : MultipartRequest<ContentMessage<StickerContent>>, Request<ContentMessage<StickerContent>> by sendStickerByFileId {
override val mediaMap: Map<String, MultipartFile> = mapOf(stickerField to sticker) override val mediaMap: Map<String, MultipartFile> = mapOf(stickerField to sticker)
override val paramsJson: JsonObject = sendStickerByFileId.toJsonWithoutNulls(SendStickerByFileId.serializer()) override val paramsJson: JsonObject
get() {
return JsonObject(
mapOfNotNull(
emojiField to emoji ?.let { JsonPrimitive(it) }
) + sendStickerByFileId.toJsonWithoutNulls(SendStickerByFileId.serializer())
)
}
} }

View File

@@ -133,8 +133,8 @@ data class SendVideoData internal constructor(
override val chatId: ChatIdentifier, override val chatId: ChatIdentifier,
@SerialName(videoField) @SerialName(videoField)
val video: String? = null, val video: String? = null,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: String? = null, override val thumbnail: String? = null,
@SerialName(captionField) @SerialName(captionField)
override val text: String? = null, override val text: String? = null,
@SerialName(parseModeField) @SerialName(parseModeField)
@@ -193,8 +193,8 @@ data class SendVideoData internal constructor(
data class SendVideoFiles internal constructor( data class SendVideoFiles internal constructor(
val video: MultipartFile? = null, val video: MultipartFile? = null,
val thumb: MultipartFile? = null val thumbnail: MultipartFile? = null
) : Files by mapOfNotNull( ) : Files by mapOfNotNull(
videoField to video, videoField to video,
thumbField to thumb thumbnailField to thumbnail
) )

View File

@@ -62,8 +62,8 @@ data class SendVideoNoteData internal constructor(
override val chatId: ChatIdentifier, override val chatId: ChatIdentifier,
@SerialName(videoNoteField) @SerialName(videoNoteField)
val videoNote: String? = null, val videoNote: String? = null,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: String? = null, override val thumbnail: String? = null,
@SerialName(durationField) @SerialName(durationField)
override val duration: Long? = null, override val duration: Long? = null,
@SerialName(lengthField) @SerialName(lengthField)
@@ -99,8 +99,8 @@ data class SendVideoNoteData internal constructor(
data class SendVideoNoteFiles internal constructor( data class SendVideoNoteFiles internal constructor(
val videoNote: MultipartFile? = null, val videoNote: MultipartFile? = null,
val thumb: MultipartFile? = null val thumbnail: MultipartFile? = null
) : Files by mapOfNotNull( ) : Files by mapOfNotNull(
videoNoteField to videoNote, videoNoteField to videoNote,
thumbField to thumb thumbnailField to thumbnail
) )

View File

@@ -156,8 +156,8 @@ data class SendVoiceData internal constructor(
data class SendVoiceFiles internal constructor( data class SendVoiceFiles internal constructor(
val voice: MultipartFile? = null, val voice: MultipartFile? = null,
val thumb: MultipartFile? = null val thumbnail: MultipartFile? = null
) : Files by mapOfNotNull( ) : Files by mapOfNotNull(
voiceField to voice, voiceField to voice,
thumbField to thumb thumbnailField to thumbnail
) )

View File

@@ -2,6 +2,7 @@ package dev.inmo.tgbotapi.requests.stickers
import dev.inmo.tgbotapi.requests.abstracts.FileId import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.requests.stickers.abstracts.StickerAction
import dev.inmo.tgbotapi.types.stickerField import dev.inmo.tgbotapi.types.stickerField
import kotlinx.serialization.* import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer import kotlinx.serialization.builtins.serializer
@@ -9,8 +10,8 @@ import kotlinx.serialization.builtins.serializer
@Serializable @Serializable
data class DeleteStickerFromSet( data class DeleteStickerFromSet(
@SerialName(stickerField) @SerialName(stickerField)
val sticker: FileId override val sticker: FileId
) : SimpleRequest<Boolean> { ) : StickerAction<Boolean> {
override fun method(): String = "deleteStickerFromSet" override fun method(): String = "deleteStickerFromSet"
override val resultDeserializer: DeserializationStrategy<Boolean> override val resultDeserializer: DeserializationStrategy<Boolean>
get() = Boolean.serializer() get() = Boolean.serializer()

View File

@@ -0,0 +1,21 @@
package dev.inmo.tgbotapi.requests.stickers
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.StickerSetName
import dev.inmo.tgbotapi.types.nameField
import dev.inmo.tgbotapi.types.stickerField
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
@Serializable
data class DeleteStickerSet(
@SerialName(nameField)
val name: StickerSetName
) : SimpleRequest<Boolean> {
override fun method(): String = "deleteStickerSet"
override val resultDeserializer: DeserializationStrategy<Boolean>
get() = Boolean.serializer()
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -0,0 +1,33 @@
package dev.inmo.tgbotapi.requests.stickers
import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest
import dev.inmo.tgbotapi.requests.stickers.abstracts.OwnerStickerSetAction
import dev.inmo.tgbotapi.requests.stickers.abstracts.StickerAction
import dev.inmo.tgbotapi.requests.stickers.abstracts.StickerSetAction
import dev.inmo.tgbotapi.types.*
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
@Serializable
data class SetStickerEmojiList (
@SerialName(stickerField)
override val sticker: FileId,
@SerialName(emojiListField)
val emojis: List<String>
) : StickerAction<Boolean> {
constructor(sticker: FileId, vararg emojis: String) : this(sticker, emojis.toList())
init {
require(emojis.size !in emojisInStickerLimit) {
"Emojis size should be in range $emojisInStickerLimit, but was ${emojis.size}"
}
}
override val resultDeserializer: DeserializationStrategy<Boolean>
get() = Boolean.serializer()
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
override fun method(): String = "setStickerEmojiList"
}

View File

@@ -0,0 +1,38 @@
package dev.inmo.tgbotapi.requests.stickers
import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest
import dev.inmo.tgbotapi.requests.stickers.abstracts.OwnerStickerSetAction
import dev.inmo.tgbotapi.requests.stickers.abstracts.StickerAction
import dev.inmo.tgbotapi.requests.stickers.abstracts.StickerSetAction
import dev.inmo.tgbotapi.types.*
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
@Serializable
data class SetStickerKeywords (
@SerialName(stickerField)
override val sticker: FileId,
@SerialName(keywordsField)
val keywords: List<String>
) : StickerAction<Boolean> {
constructor(sticker: FileId, vararg keywords: String) : this(sticker, keywords.toList())
init {
require(keywords.size !in keywordsInStickerLimit) {
"Keywords list size should be in range $keywordsInStickerLimit, but was ${keywords.size}"
}
keywords.forEach {
require(it.length in stickerKeywordLengthLimit) {
"Keyword length should be in range $stickerKeywordLengthLimit, but was ${it.length} (word \"$it\")"
}
}
}
override val resultDeserializer: DeserializationStrategy<Boolean>
get() = Boolean.serializer()
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
override fun method(): String = "setStickerKeywords"
}

View File

@@ -0,0 +1,26 @@
package dev.inmo.tgbotapi.requests.stickers
import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest
import dev.inmo.tgbotapi.requests.stickers.abstracts.OwnerStickerSetAction
import dev.inmo.tgbotapi.requests.stickers.abstracts.StickerAction
import dev.inmo.tgbotapi.requests.stickers.abstracts.StickerSetAction
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.stickers.MaskPosition
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
@Serializable
data class SetStickerMaskPosition (
@SerialName(stickerField)
override val sticker: FileId,
@SerialName(maskPositionField)
val maskPosition: MaskPosition
) : StickerAction<Boolean> {
override val resultDeserializer: DeserializationStrategy<Boolean>
get() = Boolean.serializer()
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
override fun method(): String = "setStickerMaskPosition"
}

View File

@@ -2,6 +2,7 @@ package dev.inmo.tgbotapi.requests.stickers
import dev.inmo.tgbotapi.requests.abstracts.FileId import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.requests.stickers.abstracts.StickerAction
import dev.inmo.tgbotapi.types.positionField import dev.inmo.tgbotapi.types.positionField
import dev.inmo.tgbotapi.types.stickerField import dev.inmo.tgbotapi.types.stickerField
import kotlinx.serialization.* import kotlinx.serialization.*
@@ -10,10 +11,10 @@ import kotlinx.serialization.builtins.serializer
@Serializable @Serializable
data class SetStickerPositionInSet( data class SetStickerPositionInSet(
@SerialName(stickerField) @SerialName(stickerField)
val sticker: FileId, override val sticker: FileId,
@SerialName(positionField) @SerialName(positionField)
val position: Int val position: Int
) : SimpleRequest<Boolean> { ) : StickerAction<Boolean> {
init { init {
if (position < 0) { if (position < 0) {
throw IllegalArgumentException("Position must be positive or 0") throw IllegalArgumentException("Position must be positive or 0")

View File

@@ -0,0 +1,47 @@
package dev.inmo.tgbotapi.requests.stickers
import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest
import dev.inmo.tgbotapi.requests.stickers.abstracts.OwnerStickerSetAction
import dev.inmo.tgbotapi.types.*
import kotlinx.serialization.*
fun SetStickerSetThumbnail(
userId: UserId,
stickerSetName: String,
thumbnail: MultipartFile
): Request<Boolean> {
return CommonMultipartFileRequest(
SetStickerSetThumbnail(userId, stickerSetName),
mapOf(thumbnailField to thumbnail)
)
}
@Deprecated("Renamed", ReplaceWith("SetStickerSetThumbnail(userId, stickerSetName, thumbnail)", "dev.inmo.tgbotapi.requests.stickers.SetStickerSetThumbnail"))
fun SetStickerSetThumb(
userId: UserId,
stickerSetName: String,
thumbnail: MultipartFile
): Request<Boolean> = SetStickerSetThumbnail(userId, stickerSetName, thumbnail)
@Serializable
data class SetStickerSetThumbnail (
@SerialName(userIdField)
override val userId: UserId,
@SerialName(nameField)
override val name: StickerSetName,
@SerialName(thumbnailField)
val thumbnail: FileId? = null
) : OwnerStickerSetAction {
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
override fun method(): String = "setStickerSetThumbnail"
}
@Deprecated("Renamed", ReplaceWith("SetStickerSetThumbnail(userId, name, thumbnail)", "dev.inmo.tgbotapi.requests.stickers.SetStickerSetThumbnail"))
fun SetStickerSetThumb(
userId: UserId,
name: StickerSetName,
thumbnail: FileId? = null
) = SetStickerSetThumbnail(userId, name, thumbnail)

View File

@@ -6,28 +6,15 @@ import dev.inmo.tgbotapi.requests.stickers.abstracts.StickerSetAction
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import kotlinx.serialization.* import kotlinx.serialization.*
fun SetStickerSetThumb(
userId: UserId,
stickerSetName: String,
thumb: MultipartFile
): Request<Boolean> {
return CommonMultipartFileRequest(
SetStickerSetThumb(userId, stickerSetName),
mapOf(thumbField to thumb)
)
}
@Serializable @Serializable
data class SetStickerSetThumb ( data class SetStickerSetTitle (
@SerialName(userIdField)
override val userId: UserId,
@SerialName(nameField) @SerialName(nameField)
override val name: StickerSetName, override val name: StickerSetName,
@SerialName(thumbField) @SerialName(titleField)
val thumb: FileId? = null val title: String
) : StickerSetAction { ) : StickerSetAction {
override val requestSerializer: SerializationStrategy<*> override val requestSerializer: SerializationStrategy<*>
get() = serializer() get() = serializer()
override fun method(): String = "setStickerSetThumb" override fun method(): String = "setStickerSetTitle"
} }

View File

@@ -0,0 +1,11 @@
package dev.inmo.tgbotapi.requests.stickers.abstracts
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.StickerSetName
import dev.inmo.tgbotapi.types.UserId
import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.serializer
interface OwnerStickerSetAction : StickerSetAction {
val userId: UserId
}

View File

@@ -2,7 +2,7 @@ package dev.inmo.tgbotapi.requests.stickers.abstracts
import dev.inmo.tgbotapi.types.stickers.MaskPosition import dev.inmo.tgbotapi.types.stickers.MaskPosition
interface StandardStickerSetAction : StickerSetAction { interface StandardStickerSetAction : OwnerStickerSetAction {
val emojis: String // must be more than one val emojis: String // must be more than one
val maskPosition: MaskPosition? val maskPosition: MaskPosition?
} }

View File

@@ -0,0 +1,8 @@
package dev.inmo.tgbotapi.requests.stickers.abstracts
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
interface StickerAction<T : Any> : SimpleRequest<T> {
val sticker: FileId
}

View File

@@ -1,14 +1,14 @@
package dev.inmo.tgbotapi.requests.stickers.abstracts package dev.inmo.tgbotapi.requests.stickers.abstracts
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.StickerSetName
import dev.inmo.tgbotapi.types.UserId import dev.inmo.tgbotapi.types.UserId
import kotlinx.serialization.KSerializer import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.serializer import kotlinx.serialization.builtins.serializer
interface StickerSetAction : SimpleRequest<Boolean> { interface StickerSetAction : SimpleRequest<Boolean> {
val userId: UserId val name: StickerSetName
val name: String
override val resultDeserializer: KSerializer<Boolean> override val resultDeserializer: KSerializer<Boolean>
get() = Boolean.serializer() get() = Boolean.serializer()
} }

View File

@@ -0,0 +1,10 @@
package dev.inmo.tgbotapi.types
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class BotDescription(
@SerialName(descriptionField)
val description: String
)

View File

@@ -0,0 +1,10 @@
package dev.inmo.tgbotapi.types
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class BotShortDescription(
@SerialName(shortDescriptionField)
val shortDescription: String
)

View File

@@ -134,6 +134,12 @@ val suggestedTipAmountsLimit = 1 .. 4
val inputFieldPlaceholderLimit = 1 .. 64 val inputFieldPlaceholderLimit = 1 .. 64
val emojisInStickerLimit = 1 .. 20
val keywordsInStickerLimit = 0 .. 20
val stickerKeywordLengthLimit = 0 .. 64
const val botActionActualityTime: Seconds = 5 const val botActionActualityTime: Seconds = 5
// Made as lazy for correct work in K/JS // Made as lazy for correct work in K/JS
@@ -257,6 +263,7 @@ const val createsJoinRequestField = "creates_join_request"
const val pendingJoinRequestCountField = "pending_join_request_count" const val pendingJoinRequestCountField = "pending_join_request_count"
const val memberLimitField = "member_limit" const val memberLimitField = "member_limit"
const val iconColorField = "icon_color" const val iconColorField = "icon_color"
const val emojiListField = "emoji_list"
const val requestContactField = "request_contact" const val requestContactField = "request_contact"
const val requestLocationField = "request_location" const val requestLocationField = "request_location"
@@ -325,9 +332,17 @@ const val stickerFileIdField = "sticker_file_id"
const val gameShortNameField = "game_short_name" const val gameShortNameField = "game_short_name"
const val thumbnailUrlField = "thumbnail_url"
@Deprecated("Renamed in telegram bot api", ReplaceWith("thumbnailUrlField", "dev.inmo.tgbotapi.types.thumbnailUrlField"))
const val thumbUrlField = "thumb_url" const val thumbUrlField = "thumb_url"
const val thumbnailMimeTypeField = "thumbnail_mime_type"
@Deprecated("Renamed in telegram bot api", ReplaceWith("thumbnailMimeTypeField", "dev.inmo.tgbotapi.types.thumbnailMimeTypeField"))
const val thumbMimeTypeField = "thumb_mime_type" const val thumbMimeTypeField = "thumb_mime_type"
const val thumbnailWidthField = "thumbnail_width"
@Deprecated("Renamed in telegram bot api", ReplaceWith("thumbnailWidthField", "dev.inmo.tgbotapi.types.thumbnailWidthField"))
const val thumbWidthField = "thumb_width" const val thumbWidthField = "thumb_width"
const val thumbnailHeightField = "thumbnail_height"
@Deprecated("Renamed in telegram bot api", ReplaceWith("thumbnailHeightField", "dev.inmo.tgbotapi.types.thumbnailHeightField"))
const val thumbHeightField = "thumb_height" const val thumbHeightField = "thumb_height"
const val inputMessageContentField = "input_message_content" const val inputMessageContentField = "input_message_content"
@@ -380,11 +395,14 @@ const val explanationField = "explanation"
const val idField = "id" const val idField = "id"
const val pollIdField = "poll_id" const val pollIdField = "poll_id"
const val textField = "text" const val textField = "text"
const val thumbnailField = "thumbnail"
@Deprecated("Renamed (in telegram bot api)", ReplaceWith("thumbnailField", "dev.inmo.tgbotapi.types.thumbnailField"))
const val thumbField = "thumb" const val thumbField = "thumb"
const val emojiField = "emoji" const val emojiField = "emoji"
const val emojisField = "emojis" const val emojisField = "emojis"
const val titleField = "title" const val titleField = "title"
const val descriptionField = "description" const val descriptionField = "description"
const val shortDescriptionField = "short_description"
const val performerField = "performer" const val performerField = "performer"
const val durationField = "duration" const val durationField = "duration"
const val widthField = "width" const val widthField = "width"
@@ -408,6 +426,7 @@ const val offsetField = "offset"
const val limitField = "limit" const val limitField = "limit"
const val stickersField = "stickers" const val stickersField = "stickers"
const val stickerField = "sticker" const val stickerField = "sticker"
const val keywordsField = "keywords"
const val urlField = "url" const val urlField = "url"
const val addressField = "address" const val addressField = "address"
const val actionField = "action" const val actionField = "action"

View File

@@ -23,12 +23,12 @@ class InlineQueryResultArticle(
val hideUrl: Boolean? = null, val hideUrl: Boolean? = null,
@SerialName(descriptionField) @SerialName(descriptionField)
override val description: String? = null, override val description: String? = null,
@SerialName(thumbUrlField) @SerialName(thumbnailUrlField)
override val thumbUrl: String? = null, override val thumbnailUrl: String? = null,
@SerialName(thumbWidthField) @SerialName(thumbnailWidthField)
override val thumbWidth: Int? = null, override val thumbnailWidth: Int? = null,
@SerialName(thumbHeightField) @SerialName(thumbnailHeightField)
override val thumbHeight: Int? = null override val thumbnailHeight: Int? = null
) : InlineQueryResult, ) : InlineQueryResult,
ThumbSizedInlineQueryResult, ThumbSizedInlineQueryResult,
TitledInlineQueryResult, TitledInlineQueryResult,

View File

@@ -20,12 +20,12 @@ data class InlineQueryResultContact(
override val lastName: String? = null, override val lastName: String? = null,
@SerialName(vcardField) @SerialName(vcardField)
override val vcard: String? = null, override val vcard: String? = null,
@SerialName(thumbUrlField) @SerialName(thumbnailUrlField)
override val thumbUrl: String? = null, override val thumbnailUrl: String? = null,
@SerialName(thumbWidthField) @SerialName(thumbnailWidthField)
override val thumbWidth: Int? = null, override val thumbnailWidth: Int? = null,
@SerialName(thumbHeightField) @SerialName(thumbnailHeightField)
override val thumbHeight: Int? = null, override val thumbnailHeight: Int? = null,
@SerialName(replyMarkupField) @SerialName(replyMarkupField)
override val replyMarkup: InlineKeyboardMarkup? = null, override val replyMarkup: InlineKeyboardMarkup? = null,
@SerialName(inputMessageContentField) @SerialName(inputMessageContentField)

View File

@@ -21,24 +21,24 @@ fun InlineQueryResultDocumentImpl(
url: String, url: String,
title: String, title: String,
mimeType: MimeType, mimeType: MimeType,
thumbUrl: String? = null, thumbnailUrl: String? = null,
thumbWidth: Int? = null, thumbnailWidth: Int? = null,
thumbHeight: Int? = null, thumbnailHeight: Int? = null,
description: String? = null, description: String? = null,
text: String? = null, text: String? = null,
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
replyMarkup: InlineKeyboardMarkup? = null, replyMarkup: InlineKeyboardMarkup? = null,
inputMessageContent: InputMessageContent? = null inputMessageContent: InputMessageContent? = null
) = InlineQueryResultDocumentImpl(id, url, title, mimeType, thumbUrl, thumbWidth, thumbHeight, description, text, parseMode, null, replyMarkup, inputMessageContent) ) = InlineQueryResultDocumentImpl(id, url, title, mimeType, thumbnailUrl, thumbnailWidth, thumbnailHeight, description, text, parseMode, null, replyMarkup, inputMessageContent)
fun InlineQueryResultDocumentImpl( fun InlineQueryResultDocumentImpl(
id: InlineQueryIdentifier, id: InlineQueryIdentifier,
url: String, url: String,
title: String, title: String,
mimeType: MimeType, mimeType: MimeType,
thumbUrl: String? = null, thumbnailUrl: String? = null,
thumbWidth: Int? = null, thumbnailWidth: Int? = null,
thumbHeight: Int? = null, thumbnailHeight: Int? = null,
description: String? = null, description: String? = null,
entities: TextSourcesList, entities: TextSourcesList,
replyMarkup: InlineKeyboardMarkup? = null, replyMarkup: InlineKeyboardMarkup? = null,
@@ -48,9 +48,9 @@ fun InlineQueryResultDocumentImpl(
url, url,
title, title,
mimeType, mimeType,
thumbUrl, thumbnailUrl,
thumbWidth, thumbnailWidth,
thumbHeight, thumbnailHeight,
description, description,
entities.makeString(), entities.makeString(),
null, null,
@@ -69,12 +69,12 @@ data class InlineQueryResultDocumentImpl internal constructor(
override val title: String, override val title: String,
@SerialName(mimeTypeField) @SerialName(mimeTypeField)
override val mimeType: MimeType, override val mimeType: MimeType,
@SerialName(thumbUrlField) @SerialName(thumbnailUrlField)
override val thumbUrl: String? = null, override val thumbnailUrl: String? = null,
@SerialName(thumbWidthField) @SerialName(thumbnailWidthField)
override val thumbWidth: Int? = null, override val thumbnailWidth: Int? = null,
@SerialName(thumbHeightField) @SerialName(thumbnailHeightField)
override val thumbHeight: Int? = null, override val thumbnailHeight: Int? = null,
@SerialName(descriptionField) @SerialName(descriptionField)
override val description: String? = null, override val description: String? = null,
@SerialName(captionField) @SerialName(captionField)

View File

@@ -20,8 +20,8 @@ import kotlinx.serialization.Serializable
fun InlineQueryResultGifImpl( fun InlineQueryResultGifImpl(
id: InlineQueryIdentifier, id: InlineQueryIdentifier,
url: String, url: String,
thumbUrl: String, thumbnailUrl: String,
thumbMimeType: MimeType? = null, thumbnailMimeType: MimeType? = null,
width: Int? = null, width: Int? = null,
height: Int? = null, height: Int? = null,
duration: Int? = null, duration: Int? = null,
@@ -30,13 +30,13 @@ fun InlineQueryResultGifImpl(
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
replyMarkup: InlineKeyboardMarkup? = null, replyMarkup: InlineKeyboardMarkup? = null,
inputMessageContent: InputMessageContent? = null inputMessageContent: InputMessageContent? = null
) = InlineQueryResultGifImpl(id, url, thumbUrl, thumbMimeType, width, height, duration, title, text, parseMode, null, replyMarkup, inputMessageContent) ) = InlineQueryResultGifImpl(id, url, thumbnailUrl, thumbnailMimeType, width, height, duration, title, text, parseMode, null, replyMarkup, inputMessageContent)
fun InlineQueryResultGifImpl( fun InlineQueryResultGifImpl(
id: InlineQueryIdentifier, id: InlineQueryIdentifier,
url: String, url: String,
thumbUrl: String, thumbnailUrl: String,
thumbMimeType: MimeType? = null, thumbnailMimeType: MimeType? = null,
width: Int? = null, width: Int? = null,
height: Int? = null, height: Int? = null,
duration: Int? = null, duration: Int? = null,
@@ -47,8 +47,8 @@ fun InlineQueryResultGifImpl(
) = InlineQueryResultGifImpl( ) = InlineQueryResultGifImpl(
id, id,
url, url,
thumbUrl, thumbnailUrl,
thumbMimeType, thumbnailMimeType,
width, width,
height, height,
duration, duration,
@@ -63,8 +63,8 @@ fun InlineQueryResultGifImpl(
fun InlineQueryResultGifImpl( fun InlineQueryResultGifImpl(
id: InlineQueryIdentifier, id: InlineQueryIdentifier,
gifFile: FileId, gifFile: FileId,
thumbUrl: String, thumbnailUrl: String,
thumbMimeType: MimeType? = null, thumbnailMimeType: MimeType? = null,
width: Int? = null, width: Int? = null,
height: Int? = null, height: Int? = null,
duration: Int? = null, duration: Int? = null,
@@ -73,13 +73,13 @@ fun InlineQueryResultGifImpl(
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
replyMarkup: InlineKeyboardMarkup? = null, replyMarkup: InlineKeyboardMarkup? = null,
inputMessageContent: InputMessageContent? = null inputMessageContent: InputMessageContent? = null
) = InlineQueryResultGifImpl(id, gifFile.fileId, thumbUrl, thumbMimeType, width, height, duration, title, text, parseMode, replyMarkup, inputMessageContent) ) = InlineQueryResultGifImpl(id, gifFile.fileId, thumbnailUrl, thumbnailMimeType, width, height, duration, title, text, parseMode, replyMarkup, inputMessageContent)
fun InlineQueryResultGifImpl( fun InlineQueryResultGifImpl(
id: InlineQueryIdentifier, id: InlineQueryIdentifier,
gifFile: FileId, gifFile: FileId,
thumbUrl: String, thumbnailUrl: String,
thumbMimeType: MimeType? = null, thumbnailMimeType: MimeType? = null,
width: Int? = null, width: Int? = null,
height: Int? = null, height: Int? = null,
duration: Int? = null, duration: Int? = null,
@@ -88,7 +88,7 @@ fun InlineQueryResultGifImpl(
replyMarkup: InlineKeyboardMarkup? = null, replyMarkup: InlineKeyboardMarkup? = null,
inputMessageContent: InputMessageContent? = null inputMessageContent: InputMessageContent? = null
) = InlineQueryResultGifImpl( ) = InlineQueryResultGifImpl(
id, gifFile.fileId, thumbUrl, thumbMimeType, width, height, duration, title, entities, replyMarkup, inputMessageContent id, gifFile.fileId, thumbnailUrl, thumbnailMimeType, width, height, duration, title, entities, replyMarkup, inputMessageContent
) )
@Serializable @Serializable
@@ -97,10 +97,10 @@ data class InlineQueryResultGifImpl internal constructor(
override val id: InlineQueryIdentifier, override val id: InlineQueryIdentifier,
@SerialName(gifUrlField) @SerialName(gifUrlField)
override val url: String, override val url: String,
@SerialName(thumbUrlField) @SerialName(thumbnailUrlField)
override val thumbUrl: String, override val thumbnailUrl: String,
@SerialName(thumbMimeTypeField) @SerialName(thumbnailMimeTypeField)
override val thumbMimeType: MimeType? = null, override val thumbnailMimeType: MimeType? = null,
@SerialName(gifWidthField) @SerialName(gifWidthField)
override val width: Int? = null, override val width: Int? = null,
@SerialName(gifHeightField) @SerialName(gifHeightField)
@@ -126,8 +126,8 @@ data class InlineQueryResultGifImpl internal constructor(
} }
init { init {
if (thumbMimeType != null && thumbMimeType !in telegramInlineModeGifPermittedMimeTypes) { if (thumbnailMimeType != null && thumbnailMimeType !in telegramInlineModeGifPermittedMimeTypes) {
error("Passed thumb mime type is not permitted in Telegram Bot API. Passed $thumbMimeType, but permitted $telegramInlineModeGifPermittedMimeTypes") error("Passed thumb mime type is not permitted in Telegram Bot API. Passed $thumbnailMimeType, but permitted $telegramInlineModeGifPermittedMimeTypes")
} }
} }
} }

View File

@@ -26,12 +26,12 @@ data class InlineQueryResultLocation(
override val heading: Degrees? = null, override val heading: Degrees? = null,
@SerialName(proximityAlertRadiusField) @SerialName(proximityAlertRadiusField)
override val proximityAlertRadius: Meters? = null, override val proximityAlertRadius: Meters? = null,
@SerialName(thumbUrlField) @SerialName(thumbnailUrlField)
override val thumbUrl: String? = null, override val thumbnailUrl: String? = null,
@SerialName(thumbWidthField) @SerialName(thumbnailWidthField)
override val thumbWidth: Int? = null, override val thumbnailWidth: Int? = null,
@SerialName(thumbHeightField) @SerialName(thumbnailHeightField)
override val thumbHeight: Int? = null, override val thumbnailHeight: Int? = null,
@SerialName(replyMarkupField) @SerialName(replyMarkupField)
override val replyMarkup: InlineKeyboardMarkup? = null, override val replyMarkup: InlineKeyboardMarkup? = null,
@SerialName(inputMessageContentField) @SerialName(inputMessageContentField)

View File

@@ -19,8 +19,8 @@ import kotlinx.serialization.Serializable
fun InlineQueryResultMpeg4GifImpl( fun InlineQueryResultMpeg4GifImpl(
id: InlineQueryIdentifier, id: InlineQueryIdentifier,
url: String, url: String,
thumbUrl: String, thumbnailUrl: String,
thumbMimeType: MimeType? = null, thumbnailMimeType: MimeType? = null,
width: Int? = null, width: Int? = null,
height: Int? = null, height: Int? = null,
duration: Int? = null, duration: Int? = null,
@@ -29,13 +29,13 @@ fun InlineQueryResultMpeg4GifImpl(
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
replyMarkup: InlineKeyboardMarkup? = null, replyMarkup: InlineKeyboardMarkup? = null,
inputMessageContent: InputMessageContent? = null inputMessageContent: InputMessageContent? = null
) = InlineQueryResultMpeg4GifImpl(id, url, thumbUrl, thumbMimeType, width, height, duration, title, text, parseMode, null, replyMarkup, inputMessageContent) ) = InlineQueryResultMpeg4GifImpl(id, url, thumbnailUrl, thumbnailMimeType, width, height, duration, title, text, parseMode, null, replyMarkup, inputMessageContent)
fun InlineQueryResultMpeg4GifImpl( fun InlineQueryResultMpeg4GifImpl(
id: InlineQueryIdentifier, id: InlineQueryIdentifier,
url: String, url: String,
thumbUrl: String, thumbnailUrl: String,
thumbMimeType: MimeType? = null, thumbnailMimeType: MimeType? = null,
width: Int? = null, width: Int? = null,
height: Int? = null, height: Int? = null,
duration: Int? = null, duration: Int? = null,
@@ -46,8 +46,8 @@ fun InlineQueryResultMpeg4GifImpl(
) = InlineQueryResultMpeg4GifImpl( ) = InlineQueryResultMpeg4GifImpl(
id, id,
url, url,
thumbUrl, thumbnailUrl,
thumbMimeType, thumbnailMimeType,
width, width,
height, height,
duration, duration,
@@ -65,10 +65,10 @@ data class InlineQueryResultMpeg4GifImpl internal constructor(
override val id: InlineQueryIdentifier, override val id: InlineQueryIdentifier,
@SerialName(mpeg4GifUrlField) @SerialName(mpeg4GifUrlField)
override val url: String, override val url: String,
@SerialName(thumbUrlField) @SerialName(thumbnailUrlField)
override val thumbUrl: String, override val thumbnailUrl: String,
@SerialName(thumbMimeTypeField) @SerialName(thumbnailMimeTypeField)
override val thumbMimeType: MimeType? = null, override val thumbnailMimeType: MimeType? = null,
@SerialName(mpeg4GifWidthField) @SerialName(mpeg4GifWidthField)
override val width: Int? = null, override val width: Int? = null,
@SerialName(mpeg4GifHeightField) @SerialName(mpeg4GifHeightField)
@@ -94,8 +94,8 @@ data class InlineQueryResultMpeg4GifImpl internal constructor(
} }
init { init {
if (thumbMimeType != null && thumbMimeType !in telegramInlineModeGifPermittedMimeTypes) { if (thumbnailMimeType != null && thumbnailMimeType !in telegramInlineModeGifPermittedMimeTypes) {
error("Passed thumb mime type is not permitted in Telegram Bot API. Passed $thumbMimeType, but permitted $telegramInlineModeGifPermittedMimeTypes") error("Passed thumb mime type is not permitted in Telegram Bot API. Passed $thumbnailMimeType, but permitted $telegramInlineModeGifPermittedMimeTypes")
} }
} }
} }

View File

@@ -18,7 +18,7 @@ import kotlinx.serialization.Serializable
fun InlineQueryResultPhotoImpl( fun InlineQueryResultPhotoImpl(
id: InlineQueryIdentifier, id: InlineQueryIdentifier,
url: String, url: String,
thumbUrl: String, thumbnailUrl: String,
width: Int? = null, width: Int? = null,
height: Int? = null, height: Int? = null,
title: String? = null, title: String? = null,
@@ -27,12 +27,12 @@ fun InlineQueryResultPhotoImpl(
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
replyMarkup: InlineKeyboardMarkup? = null, replyMarkup: InlineKeyboardMarkup? = null,
inputMessageContent: InputMessageContent? = null inputMessageContent: InputMessageContent? = null
) = InlineQueryResultPhotoImpl(id, url, thumbUrl, width, height, title, description, text, parseMode, null, replyMarkup, inputMessageContent) ) = InlineQueryResultPhotoImpl(id, url, thumbnailUrl, width, height, title, description, text, parseMode, null, replyMarkup, inputMessageContent)
fun InlineQueryResultPhotoImpl( fun InlineQueryResultPhotoImpl(
id: InlineQueryIdentifier, id: InlineQueryIdentifier,
url: String, url: String,
thumbUrl: String, thumbnailUrl: String,
width: Int? = null, width: Int? = null,
height: Int? = null, height: Int? = null,
title: String? = null, title: String? = null,
@@ -43,7 +43,7 @@ fun InlineQueryResultPhotoImpl(
) = InlineQueryResultPhotoImpl( ) = InlineQueryResultPhotoImpl(
id, id,
url, url,
thumbUrl, thumbnailUrl,
width, width,
height, height,
title, title,
@@ -61,8 +61,8 @@ data class InlineQueryResultPhotoImpl internal constructor(
override val id: InlineQueryIdentifier, override val id: InlineQueryIdentifier,
@SerialName(photoUrlField) @SerialName(photoUrlField)
override val url: String, override val url: String,
@SerialName(thumbUrlField) @SerialName(thumbnailUrlField)
override val thumbUrl: String, override val thumbnailUrl: String,
@SerialName(photoWidthField) @SerialName(photoWidthField)
override val width: Int? = null, override val width: Int? = null,
@SerialName(photoHeightField) @SerialName(photoHeightField)

View File

@@ -29,12 +29,12 @@ data class InlineQueryResultVenue(
override val googlePlaceId: GooglePlaceId? = null, override val googlePlaceId: GooglePlaceId? = null,
@SerialName(googlePlaceTypeField) @SerialName(googlePlaceTypeField)
override val googlePlaceType: GooglePlaceType? = null, override val googlePlaceType: GooglePlaceType? = null,
@SerialName(thumbUrlField) @SerialName(thumbnailUrlField)
override val thumbUrl: String? = null, override val thumbnailUrl: String? = null,
@SerialName(thumbWidthField) @SerialName(thumbnailWidthField)
override val thumbWidth: Int? = null, override val thumbnailWidth: Int? = null,
@SerialName(thumbHeightField) @SerialName(thumbnailHeightField)
override val thumbHeight: Int? = null, override val thumbnailHeight: Int? = null,
@SerialName(replyMarkupField) @SerialName(replyMarkupField)
override val replyMarkup: InlineKeyboardMarkup? = null, override val replyMarkup: InlineKeyboardMarkup? = null,
@SerialName(inputMessageContentField) @SerialName(inputMessageContentField)

View File

@@ -19,7 +19,7 @@ import kotlinx.serialization.Serializable
fun InlineQueryResultVideoImpl( fun InlineQueryResultVideoImpl(
id: InlineQueryIdentifier, id: InlineQueryIdentifier,
url: String, url: String,
thumbUrl: String, thumbnailUrl: String,
mimeType: MimeType, mimeType: MimeType,
title: String, title: String,
width: Int? = null, width: Int? = null,
@@ -30,12 +30,12 @@ fun InlineQueryResultVideoImpl(
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
replyMarkup: InlineKeyboardMarkup? = null, replyMarkup: InlineKeyboardMarkup? = null,
inputMessageContent: InputMessageContent? = null inputMessageContent: InputMessageContent? = null
) = InlineQueryResultVideoImpl(id, url, thumbUrl, mimeType, title, width, height, duration, description, text, parseMode, null, replyMarkup, inputMessageContent) ) = InlineQueryResultVideoImpl(id, url, thumbnailUrl, mimeType, title, width, height, duration, description, text, parseMode, null, replyMarkup, inputMessageContent)
fun InlineQueryResultVideoImpl( fun InlineQueryResultVideoImpl(
id: InlineQueryIdentifier, id: InlineQueryIdentifier,
url: String, url: String,
thumbUrl: String, thumbnailUrl: String,
mimeType: MimeType, mimeType: MimeType,
title: String, title: String,
width: Int? = null, width: Int? = null,
@@ -48,7 +48,7 @@ fun InlineQueryResultVideoImpl(
) = InlineQueryResultVideoImpl( ) = InlineQueryResultVideoImpl(
id, id,
url, url,
thumbUrl, thumbnailUrl,
mimeType, mimeType,
title, title,
width, width,
@@ -68,8 +68,8 @@ data class InlineQueryResultVideoImpl internal constructor(
override val id: InlineQueryIdentifier, override val id: InlineQueryIdentifier,
@SerialName(videoUrlField) @SerialName(videoUrlField)
override val url: String, override val url: String,
@SerialName(thumbUrlField) @SerialName(thumbnailUrlField)
override val thumbUrl: String, override val thumbnailUrl: String,
@SerialName(mimeTypeField) @SerialName(mimeTypeField)
override val mimeType: MimeType, override val mimeType: MimeType,
@SerialName(titleField) @SerialName(titleField)

View File

@@ -1,6 +1,12 @@
package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts
interface ThumbSizedInlineQueryResult : InlineQueryResult, ThumbedInlineQueryResult { interface ThumbSizedInlineQueryResult : InlineQueryResult, ThumbedInlineQueryResult {
val thumbnailWidth: Int?
@Deprecated("Renamed in telegram bot api", ReplaceWith("thumbnailWidth"))
val thumbWidth: Int? val thumbWidth: Int?
get() = thumbnailWidth
val thumbnailHeight: Int?
@Deprecated("Renamed in telegram bot api", ReplaceWith("thumbnailHeight"))
val thumbHeight: Int? val thumbHeight: Int?
} get() = thumbnailHeight
}

View File

@@ -3,9 +3,15 @@ package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts
import dev.inmo.tgbotapi.utils.MimeType import dev.inmo.tgbotapi.utils.MimeType
interface ThumbedInlineQueryResult : InlineQueryResult { interface ThumbedInlineQueryResult : InlineQueryResult {
val thumbnailUrl: String?
@Deprecated("Renamed in telegram bot api", ReplaceWith("thumbnailUrl"))
val thumbUrl: String? val thumbUrl: String?
get() = thumbnailUrl
} }
interface ThumbedWithMimeTypeInlineQueryResult : ThumbedInlineQueryResult { interface ThumbedWithMimeTypeInlineQueryResult : ThumbedInlineQueryResult {
val thumbnailMimeType: MimeType?
@Deprecated("Renamed in telegram bot api", ReplaceWith("thumbnailMimeType"))
val thumbMimeType: MimeType? val thumbMimeType: MimeType?
} get() = thumbnailMimeType
}

View File

@@ -3,10 +3,11 @@ package dev.inmo.tgbotapi.types.InlineQueries.query
import dev.inmo.tgbotapi.types.InlineQueryIdentifier import dev.inmo.tgbotapi.types.InlineQueryIdentifier
import dev.inmo.tgbotapi.types.chat.User import dev.inmo.tgbotapi.types.chat.User
import dev.inmo.tgbotapi.types.chat.ChatType import dev.inmo.tgbotapi.types.chat.ChatType
import dev.inmo.tgbotapi.types.chat.CommonUser
data class BaseInlineQuery( data class BaseInlineQuery(
override val id: InlineQueryIdentifier, override val id: InlineQueryIdentifier,
override val from: User, override val from: CommonUser,
override val query: String, override val query: String,
override val offset: String, override val offset: String,
override val chatType: ChatType? override val chatType: ChatType?

View File

@@ -3,10 +3,16 @@ package dev.inmo.tgbotapi.types.InlineQueries.query
import dev.inmo.tgbotapi.abstracts.FromUser import dev.inmo.tgbotapi.abstracts.FromUser
import dev.inmo.tgbotapi.types.InlineQueryIdentifier import dev.inmo.tgbotapi.types.InlineQueryIdentifier
import dev.inmo.tgbotapi.types.chat.ChatType import dev.inmo.tgbotapi.types.chat.ChatType
import dev.inmo.tgbotapi.types.chat.CommonUser
import dev.inmo.tgbotapi.types.chat.User
sealed interface InlineQuery : FromUser { sealed interface InlineQuery : FromUser {
val id: InlineQueryIdentifier val id: InlineQueryIdentifier
val query: String val query: String
val offset: String val offset: String
val chatType: ChatType? val chatType: ChatType?
override val from: CommonUser
override val user: CommonUser
get() = from
} }

View File

@@ -3,11 +3,12 @@ package dev.inmo.tgbotapi.types.InlineQueries.query
import dev.inmo.tgbotapi.types.InlineQueryIdentifier import dev.inmo.tgbotapi.types.InlineQueryIdentifier
import dev.inmo.tgbotapi.types.chat.User import dev.inmo.tgbotapi.types.chat.User
import dev.inmo.tgbotapi.types.chat.ChatType import dev.inmo.tgbotapi.types.chat.ChatType
import dev.inmo.tgbotapi.types.chat.CommonUser
import dev.inmo.tgbotapi.types.location.Location import dev.inmo.tgbotapi.types.location.Location
data class LocationInlineQuery( data class LocationInlineQuery(
override val id: InlineQueryIdentifier, override val id: InlineQueryIdentifier,
override val from: User, override val from: CommonUser,
override val query: String, override val query: String,
override val offset: String, override val offset: String,
override val chatType: ChatType?, override val chatType: ChatType?,

View File

@@ -12,7 +12,7 @@ internal data class RawInlineQuery(
@SerialName(idField) @SerialName(idField)
val id: InlineQueryIdentifier, val id: InlineQueryIdentifier,
@SerialName(fromField) @SerialName(fromField)
val from: User, val from: CommonUser,
@SerialName(queryField) @SerialName(queryField)
val query: String, val query: String,
@SerialName(offsetField) @SerialName(offsetField)

View File

@@ -16,7 +16,7 @@ data class AnimationFile(
override val width: Int, override val width: Int,
override val height: Int, override val height: Int,
override val duration: Long? = null, override val duration: Long? = null,
override val thumb: PhotoSize? = null, override val thumbnail: PhotoSize? = null,
@SerialName(fileNameField) @SerialName(fileNameField)
override val fileName: String? = null, override val fileName: String? = null,
@SerialName(mimeTypeField) @SerialName(mimeTypeField)

View File

@@ -25,8 +25,8 @@ data class AudioFile(
override val mimeType: MimeType? = null, override val mimeType: MimeType? = null,
@SerialName(fileSizeField) @SerialName(fileSizeField)
override val fileSize: Long? = null, override val fileSize: Long? = null,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: PhotoSize? = null override val thumbnail: PhotoSize? = null
) : TelegramMediaFile, CustomNamedMediaFile, MimedMediaFile, ThumbedMediaFile, PlayableMediaFile, TitledMediaFile, ) : TelegramMediaFile, CustomNamedMediaFile, MimedMediaFile, ThumbedMediaFile, PlayableMediaFile, TitledMediaFile,
Performerable Performerable

View File

@@ -15,7 +15,7 @@ data class DocumentFile(
override val fileUniqueId: FileUniqueId, override val fileUniqueId: FileUniqueId,
@SerialName(fileSizeField) @SerialName(fileSizeField)
override val fileSize: Long? = null, override val fileSize: Long? = null,
override val thumb: PhotoSize? = null, override val thumbnail: PhotoSize? = null,
@SerialName(mimeTypeField) @SerialName(mimeTypeField)
override val mimeType: MimeType? = null, override val mimeType: MimeType? = null,
@SerialName(fileNameField) @SerialName(fileNameField)
@@ -30,7 +30,7 @@ inline fun TelegramMediaFile.asDocumentFile() = if (this is DocumentFile) {
fileId, fileId,
fileUniqueId, fileUniqueId,
fileSize, fileSize,
(this as? ThumbedMediaFile) ?.thumb, (this as? ThumbedMediaFile) ?.thumbnail,
(this as? MimedMediaFile) ?.mimeType, (this as? MimedMediaFile) ?.mimeType,
(this as? CustomNamedMediaFile) ?.fileName (this as? CustomNamedMediaFile) ?.fileName
) )

View File

@@ -202,8 +202,8 @@ data class RegularSimpleSticker(
override val width: Int, override val width: Int,
@SerialName(heightField) @SerialName(heightField)
override val height: Int, override val height: Int,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: PhotoSize? = null, override val thumbnail: PhotoSize? = null,
@SerialName(emojiField) @SerialName(emojiField)
override val emoji: String? = null, override val emoji: String? = null,
@SerialName(stickerSetNameField) @SerialName(stickerSetNameField)
@@ -225,8 +225,8 @@ data class RegularAnimatedSticker(
override val width: Int, override val width: Int,
@SerialName(heightField) @SerialName(heightField)
override val height: Int, override val height: Int,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: PhotoSize? = null, override val thumbnail: PhotoSize? = null,
@SerialName(emojiField) @SerialName(emojiField)
override val emoji: String? = null, override val emoji: String? = null,
@SerialName(stickerSetNameField) @SerialName(stickerSetNameField)
@@ -246,8 +246,8 @@ data class RegularVideoSticker(
override val width: Int, override val width: Int,
@SerialName(heightField) @SerialName(heightField)
override val height: Int, override val height: Int,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: PhotoSize? = null, override val thumbnail: PhotoSize? = null,
@SerialName(emojiField) @SerialName(emojiField)
override val emoji: String? = null, override val emoji: String? = null,
@SerialName(stickerSetNameField) @SerialName(stickerSetNameField)
@@ -275,8 +275,8 @@ data class MaskSimpleSticker(
override val height: Int, override val height: Int,
@SerialName(maskPositionField) @SerialName(maskPositionField)
override val maskPosition: MaskPosition, override val maskPosition: MaskPosition,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: PhotoSize? = null, override val thumbnail: PhotoSize? = null,
@SerialName(emojiField) @SerialName(emojiField)
override val emoji: String? = null, override val emoji: String? = null,
@SerialName(stickerSetNameField) @SerialName(stickerSetNameField)
@@ -296,8 +296,8 @@ data class MaskAnimatedSticker(
override val height: Int, override val height: Int,
@SerialName(maskPositionField) @SerialName(maskPositionField)
override val maskPosition: MaskPosition, override val maskPosition: MaskPosition,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: PhotoSize? = null, override val thumbnail: PhotoSize? = null,
@SerialName(emojiField) @SerialName(emojiField)
override val emoji: String? = null, override val emoji: String? = null,
@SerialName(stickerSetNameField) @SerialName(stickerSetNameField)
@@ -317,8 +317,8 @@ data class MaskVideoSticker(
override val height: Int, override val height: Int,
@SerialName(maskPositionField) @SerialName(maskPositionField)
override val maskPosition: MaskPosition, override val maskPosition: MaskPosition,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: PhotoSize? = null, override val thumbnail: PhotoSize? = null,
@SerialName(emojiField) @SerialName(emojiField)
override val emoji: String? = null, override val emoji: String? = null,
@SerialName(stickerSetNameField) @SerialName(stickerSetNameField)
@@ -344,8 +344,8 @@ data class CustomEmojiSimpleSticker(
override val height: Int, override val height: Int,
@SerialName(customEmojiIdField) @SerialName(customEmojiIdField)
override val customEmojiId: CustomEmojiId, override val customEmojiId: CustomEmojiId,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: PhotoSize? = null, override val thumbnail: PhotoSize? = null,
@SerialName(emojiField) @SerialName(emojiField)
override val emoji: String? = null, override val emoji: String? = null,
@SerialName(stickerSetNameField) @SerialName(stickerSetNameField)
@@ -365,8 +365,8 @@ data class CustomEmojiAnimatedSticker(
override val height: Int, override val height: Int,
@SerialName(customEmojiIdField) @SerialName(customEmojiIdField)
override val customEmojiId: CustomEmojiId, override val customEmojiId: CustomEmojiId,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: PhotoSize? = null, override val thumbnail: PhotoSize? = null,
@SerialName(emojiField) @SerialName(emojiField)
override val emoji: String? = null, override val emoji: String? = null,
@SerialName(stickerSetNameField) @SerialName(stickerSetNameField)
@@ -386,8 +386,8 @@ data class CustomEmojiVideoSticker(
override val height: Int, override val height: Int,
@SerialName(customEmojiIdField) @SerialName(customEmojiIdField)
override val customEmojiId: CustomEmojiId, override val customEmojiId: CustomEmojiId,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: PhotoSize? = null, override val thumbnail: PhotoSize? = null,
@SerialName(emojiField) @SerialName(emojiField)
override val emoji: String? = null, override val emoji: String? = null,
@SerialName(stickerSetNameField) @SerialName(stickerSetNameField)
@@ -406,8 +406,8 @@ data class UnknownSticker(
override val width: Int, override val width: Int,
@SerialName(heightField) @SerialName(heightField)
override val height: Int, override val height: Int,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: PhotoSize? = null, override val thumbnail: PhotoSize? = null,
@SerialName(emojiField) @SerialName(emojiField)
override val emoji: String? = null, override val emoji: String? = null,
@SerialName(stickerSetNameField) @SerialName(stickerSetNameField)

View File

@@ -1,8 +1,9 @@
package dev.inmo.tgbotapi.types.files package dev.inmo.tgbotapi.types.files
import dev.inmo.tgbotapi.types.files.PhotoSize
import dev.inmo.tgbotapi.types.files.TelegramMediaFile
sealed interface ThumbedMediaFile : TelegramMediaFile { sealed interface ThumbedMediaFile : TelegramMediaFile {
val thumbnail: PhotoSize?
@Deprecated("Renamed (in telegram bot api)", ReplaceWith("thumbnail"))
val thumb: PhotoSize? val thumb: PhotoSize?
get() = thumbnail
} }

View File

@@ -21,8 +21,8 @@ data class VideoFile(
override val height: Int, override val height: Int,
@SerialName(durationField) @SerialName(durationField)
override val duration: Long? = null, override val duration: Long? = null,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: PhotoSize? = null, override val thumbnail: PhotoSize? = null,
@SerialName(fileNameField) @SerialName(fileNameField)
override val fileName: String? = null, override val fileName: String? = null,
@SerialName(mimeTypeField) @SerialName(mimeTypeField)
@@ -44,7 +44,7 @@ inline fun VideoFile.toTelegramMediaVideo(
width, width,
height, height,
duration, duration,
thumb ?.fileId thumbnail ?.fileId
) )
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
@@ -58,5 +58,5 @@ inline fun VideoFile.toTelegramMediaVideo(
width, width,
height, height,
duration, duration,
thumb ?.fileId thumbnail ?.fileId
) )

View File

@@ -15,7 +15,7 @@ data class VideoNoteFile(
@SerialName("length") @SerialName("length")
override val width: Int, override val width: Int,
override val duration: Long? = null, override val duration: Long? = null,
override val thumb: PhotoSize? = null, override val thumbnail: PhotoSize? = null,
@SerialName(fileSizeField) @SerialName(fileSizeField)
override val fileSize: Long? = null override val fileSize: Long? = null
) : TelegramMediaFile, ThumbedMediaFile, PlayableMediaFile, SizedMediaFile { ) : TelegramMediaFile, ThumbedMediaFile, PlayableMediaFile, SizedMediaFile {

View File

@@ -77,7 +77,7 @@ fun AudioFile.toTelegramMediaAudio(
duration, duration,
performer, performer,
title, title,
thumb ?.fileId thumbnail ?.fileId
) )
fun AudioFile.toTelegramMediaAudio( fun AudioFile.toTelegramMediaAudio(
@@ -89,5 +89,5 @@ fun AudioFile.toTelegramMediaAudio(
duration, duration,
performer, performer,
title, title,
thumb ?.fileId thumbnail ?.fileId
) )

View File

@@ -78,7 +78,7 @@ fun DocumentFile.toTelegramMediaDocument(
fileId, fileId,
text, text,
parseMode, parseMode,
thumb ?.fileId thumbnail ?.fileId
) )
fun DocumentFile.toTelegramMediaDocument( fun DocumentFile.toTelegramMediaDocument(
@@ -86,5 +86,5 @@ fun DocumentFile.toTelegramMediaDocument(
) = TelegramMediaDocument( ) = TelegramMediaDocument(
fileId, fileId,
textSources, textSources,
thumb ?.fileId thumbnail ?.fileId
) )

View File

@@ -32,7 +32,7 @@ data class AnimationContent(
): Request<ContentMessage<AnimationContent>> = SendAnimation( ): Request<ContentMessage<AnimationContent>> = SendAnimation(
chatId, chatId,
media.fileId, media.fileId,
media.thumb ?.fileId, media.thumbnail ?.fileId,
textSources, textSources,
spoilered, spoilered,
media.duration, media.duration,
@@ -53,6 +53,6 @@ data class AnimationContent(
media.width, media.width,
media.height, media.height,
media.duration, media.duration,
media.thumb ?.fileId media.thumbnail ?.fileId
) )
} }

View File

@@ -30,7 +30,7 @@ data class AudioContent(
): Request<ContentMessage<AudioContent>> = SendAudio( ): Request<ContentMessage<AudioContent>> = SendAudio(
chatId, chatId,
media.fileId, media.fileId,
media.thumb ?.fileId, media.thumbnail ?.fileId,
textSources, textSources,
media.duration, media.duration,
media.performer, media.performer,

View File

@@ -32,7 +32,7 @@ data class DocumentContent(
): Request<ContentMessage<DocumentContent>> = SendDocument( ): Request<ContentMessage<DocumentContent>> = SendDocument(
chatId, chatId,
media.fileId, media.fileId,
media.thumb ?.fileId, media.thumbnail ?.fileId,
textSources, textSources,
messageThreadId, messageThreadId,
disableNotification, disableNotification,

View File

@@ -37,6 +37,6 @@ data class StickerContent(
override fun asTelegramMedia(): TelegramMediaDocument = TelegramMediaDocument( override fun asTelegramMedia(): TelegramMediaDocument = TelegramMediaDocument(
media.fileId, media.fileId,
null, null,
thumb = media.thumb ?.fileId thumb = media.thumbnail ?.fileId
) )
} }

View File

@@ -31,7 +31,7 @@ data class VideoContent(
): Request<ContentMessage<VideoContent>> = SendVideo( ): Request<ContentMessage<VideoContent>> = SendVideo(
chatId, chatId,
media.fileId, media.fileId,
media.thumb ?.fileId, media.thumbnail ?.fileId,
textSources, textSources,
spoilered, spoilered,
media.duration, media.duration,

View File

@@ -26,7 +26,7 @@ data class VideoNoteContent(
): Request<ContentMessage<VideoNoteContent>> = SendVideoNote( ): Request<ContentMessage<VideoNoteContent>> = SendVideoNote(
chatId, chatId,
media.fileId, media.fileId,
media.thumb ?.fileId, media.thumbnail ?.fileId,
media.duration, media.duration,
media.width, media.width,
messageThreadId, messageThreadId,
@@ -42,6 +42,6 @@ data class VideoNoteContent(
width = media.width, width = media.width,
height = media.height, height = media.height,
duration = media.duration, duration = media.duration,
thumb = media.thumb ?.fileId thumb = media.thumbnail ?.fileId
) )
} }

View File

@@ -9,6 +9,8 @@ sealed interface CallbackQuery : FromUser {
val id: CallbackQueryIdentifier val id: CallbackQueryIdentifier
val chatInstance: String val chatInstance: String
override val from: CommonUser override val from: CommonUser
override val user: CommonUser
get() = from
} }
data class UnknownCallbackQueryType( data class UnknownCallbackQueryType(

View File

@@ -7,7 +7,6 @@ import kotlinx.serialization.*
import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonElement
@Serializable @Serializable
@@ -146,7 +145,7 @@ data class RegularSimpleStickerSet(
override val title: String, override val title: String,
@SerialName(stickersField) @SerialName(stickersField)
override val stickers: List<RegularSimpleSticker>, override val stickers: List<RegularSimpleSticker>,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: PhotoSize? = null override val thumb: PhotoSize? = null
) : RegularStickerSet { ) : RegularStickerSet {
@SerialName(stickerTypeField) @SerialName(stickerTypeField)
@@ -162,7 +161,7 @@ data class RegularAnimatedStickerSet(
override val title: String, override val title: String,
@SerialName(stickersField) @SerialName(stickersField)
override val stickers: List<RegularAnimatedSticker>, override val stickers: List<RegularAnimatedSticker>,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: PhotoSize? = null override val thumb: PhotoSize? = null
) : RegularStickerSet, AnimatedStickerSet { ) : RegularStickerSet, AnimatedStickerSet {
@SerialName(stickerTypeField) @SerialName(stickerTypeField)
@@ -178,7 +177,7 @@ data class RegularVideoStickerSet(
override val title: String, override val title: String,
@SerialName(stickersField) @SerialName(stickersField)
override val stickers: List<RegularVideoSticker>, override val stickers: List<RegularVideoSticker>,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: PhotoSize? = null override val thumb: PhotoSize? = null
) : RegularStickerSet, VideoStickerSet { ) : RegularStickerSet, VideoStickerSet {
@SerialName(stickerTypeField) @SerialName(stickerTypeField)
@@ -194,7 +193,7 @@ data class MaskSimpleStickerSet(
override val title: String, override val title: String,
@SerialName(stickersField) @SerialName(stickersField)
override val stickers: List<MaskSimpleSticker>, override val stickers: List<MaskSimpleSticker>,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: PhotoSize? = null override val thumb: PhotoSize? = null
) : MaskStickerSet { ) : MaskStickerSet {
@SerialName(stickerTypeField) @SerialName(stickerTypeField)
@@ -210,7 +209,7 @@ data class MaskAnimatedStickerSet(
override val title: String, override val title: String,
@SerialName(stickersField) @SerialName(stickersField)
override val stickers: List<MaskAnimatedSticker>, override val stickers: List<MaskAnimatedSticker>,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: PhotoSize? = null override val thumb: PhotoSize? = null
) : MaskStickerSet, AnimatedStickerSet { ) : MaskStickerSet, AnimatedStickerSet {
@SerialName(stickerTypeField) @SerialName(stickerTypeField)
@@ -226,7 +225,7 @@ data class MaskVideoStickerSet(
override val title: String, override val title: String,
@SerialName(stickersField) @SerialName(stickersField)
override val stickers: List<MaskVideoSticker>, override val stickers: List<MaskVideoSticker>,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: PhotoSize? = null override val thumb: PhotoSize? = null
) : MaskStickerSet, VideoStickerSet { ) : MaskStickerSet, VideoStickerSet {
@SerialName(stickerTypeField) @SerialName(stickerTypeField)
@@ -242,7 +241,7 @@ data class CustomEmojiSimpleStickerSet(
override val title: String, override val title: String,
@SerialName(stickersField) @SerialName(stickersField)
override val stickers: List<CustomEmojiSimpleSticker>, override val stickers: List<CustomEmojiSimpleSticker>,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: PhotoSize? = null override val thumb: PhotoSize? = null
) : CustomEmojiStickerSet { ) : CustomEmojiStickerSet {
@SerialName(stickerTypeField) @SerialName(stickerTypeField)
@@ -258,7 +257,7 @@ data class CustomEmojiAnimatedStickerSet(
override val title: String, override val title: String,
@SerialName(stickersField) @SerialName(stickersField)
override val stickers: List<CustomEmojiAnimatedSticker>, override val stickers: List<CustomEmojiAnimatedSticker>,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: PhotoSize? = null override val thumb: PhotoSize? = null
) : CustomEmojiStickerSet, AnimatedStickerSet { ) : CustomEmojiStickerSet, AnimatedStickerSet {
@SerialName(stickerTypeField) @SerialName(stickerTypeField)
@@ -274,7 +273,7 @@ data class CustomEmojiVideoStickerSet(
override val title: String, override val title: String,
@SerialName(stickersField) @SerialName(stickersField)
override val stickers: List<CustomEmojiVideoSticker>, override val stickers: List<CustomEmojiVideoSticker>,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: PhotoSize? = null override val thumb: PhotoSize? = null
) : CustomEmojiStickerSet, VideoStickerSet { ) : CustomEmojiStickerSet, VideoStickerSet {
@SerialName(stickerTypeField) @SerialName(stickerTypeField)
@@ -292,7 +291,7 @@ data class UnknownStickerSet(
override val stickers: List<Sticker>, override val stickers: List<Sticker>,
@SerialName(stickerTypeField) @SerialName(stickerTypeField)
override val stickerType: StickerType, override val stickerType: StickerType,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: PhotoSize? = null, override val thumb: PhotoSize? = null,
val raw: JsonElement val raw: JsonElement
) : CustomEmojiStickerSet, VideoStickerSet ) : CustomEmojiStickerSet, VideoStickerSet

View File

@@ -1,6 +1,7 @@
plugins { plugins {
id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization" id "org.jetbrains.kotlin.plugin.serialization"
id "org.jetbrains.dokka"
} }
project.description = "Additional extensions for core part of tgbotapi" project.description = "Additional extensions for core part of tgbotapi"

View File

@@ -27,7 +27,8 @@ fun List<Update>.lastUpdateIdentifier(): UpdateIdentifier? {
} }
/** /**
* Will convert incoming list of updates to list with [MediaGroupUpdate]s * Will convert incoming list of [Update]s to list with [Update]s, which include [dev.inmo.tgbotapi.types.message.abstracts.ContentMessage]s
* with [dev.inmo.tgbotapi.types.message.content.MediaGroupContent]
*/ */
fun List<Update>.convertWithMediaGroupUpdates(): List<Update> { fun List<Update>.convertWithMediaGroupUpdates(): List<Update> {
val resultUpdates = mutableListOf<Update>() val resultUpdates = mutableListOf<Update>()
@@ -67,4 +68,5 @@ fun List<Update>.convertWithMediaGroupUpdates(): List<Update> {
* *
* @throws IllegalStateException * @throws IllegalStateException
*/ */
@Deprecated("Redundant", ReplaceWith("this"))
fun BaseEditMessageUpdate.toEditMediaGroupUpdate() = this fun BaseEditMessageUpdate.toEditMediaGroupUpdate() = this

View File

@@ -19,12 +19,18 @@ import io.ktor.utils.io.CancellationException
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
/**
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
* retrieved in different updates
*/
fun TelegramBot.longPollingFlow( fun TelegramBot.longPollingFlow(
timeoutSeconds: Seconds = 30, timeoutSeconds: Seconds = 30,
exceptionsHandler: (ExceptionHandler<Unit>)? = null, exceptionsHandler: (ExceptionHandler<Unit>)? = null,
allowedUpdates: List<String>? = ALL_UPDATES_LIST, allowedUpdates: List<String>? = ALL_UPDATES_LIST,
autoDisableWebhooks: Boolean = true, autoDisableWebhooks: Boolean = true,
autoSkipTimeoutExceptions: Boolean = true autoSkipTimeoutExceptions: Boolean = true,
mediaGroupsDebounceTimeMillis: Long? = 1000L,
): Flow<Update> = channelFlow { ): Flow<Update> = channelFlow {
if (autoDisableWebhooks) { if (autoDisableWebhooks) {
runCatchingSafely { runCatchingSafely {
@@ -47,6 +53,52 @@ fun TelegramBot.longPollingFlow(
var lastUpdateIdentifier: UpdateIdentifier? = null var lastUpdateIdentifier: UpdateIdentifier? = null
val updatesHandler: (suspend (List<Update>) -> Unit) = if (mediaGroupsDebounceTimeMillis != null) {
val scope = CoroutineScope(contextToWork)
val updatesReceiver = scope.updateHandlerWithMediaGroupsAdaptation(
{
withContext(contextToWork) {
send(it)
}
},
mediaGroupsDebounceTimeMillis
);
{ originalUpdates: List<Update> ->
originalUpdates.forEach {
updatesReceiver(it)
lastUpdateIdentifier = maxOf(lastUpdateIdentifier ?: it.updateId, it.updateId)
}
}
} else {
{ originalUpdates: List<Update> ->
val converted = originalUpdates.convertWithMediaGroupUpdates()
/**
* Dirty hack for cases when the media group was retrieved not fully:
*
* We are throw out the last media group and will reretrieve it again in the next get updates
* and it will guarantee that it is full
*/
val updates = if (
originalUpdates.size == getUpdatesLimit.last
&& ((converted.last() as? BaseSentMessageUpdate) ?.data as? CommonMessage<*>) ?.content is MediaGroupContent<*>
) {
converted - converted.last()
} else {
converted
}
safelyWithResult {
for (update in updates) {
send(update)
lastUpdateIdentifier = update.updateId
}
}.onFailure {
cancel(it as? CancellationException ?: return@onFailure)
}
}
}
withContext(contextToWork) { withContext(contextToWork) {
while (isActive) { while (isActive) {
safely( safely(
@@ -64,50 +116,25 @@ fun TelegramBot.longPollingFlow(
} }
} }
) { ) {
val updates = execute( execute(
GetUpdates( GetUpdates(
offset = lastUpdateIdentifier?.plus(1), offset = lastUpdateIdentifier?.plus(1),
timeout = timeoutSeconds, timeout = timeoutSeconds,
allowed_updates = allowedUpdates allowed_updates = allowedUpdates
) )
).let { originalUpdates -> ).let { originalUpdates ->
val converted = originalUpdates.convertWithMediaGroupUpdates() updatesHandler(originalUpdates)
/**
* Dirty hack for cases when the media group was retrieved not fully:
*
* We are throw out the last media group and will reretrieve it again in the next get updates
* and it will guarantee that it is full
*/
/**
* Dirty hack for cases when the media group was retrieved not fully:
*
* We are throw out the last media group and will reretrieve it again in the next get updates
* and it will guarantee that it is full
*/
if (
originalUpdates.size == getUpdatesLimit.last
&& ((converted.last() as? BaseSentMessageUpdate) ?.data as? CommonMessage<*>) ?.content is MediaGroupContent<*>
) {
converted - converted.last()
} else {
converted
}
}
safelyWithResult {
for (update in updates) {
send(update)
lastUpdateIdentifier = update.updateId
}
}.onFailure {
cancel(it as? CancellationException ?: return@onFailure)
} }
} }
} }
} }
} }
/**
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
* retrieved in different updates
*/
fun TelegramBot.startGettingOfUpdatesByLongPolling( fun TelegramBot.startGettingOfUpdatesByLongPolling(
timeoutSeconds: Seconds = 30, timeoutSeconds: Seconds = 30,
scope: CoroutineScope = CoroutineScope(Dispatchers.Default), scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
@@ -115,13 +142,15 @@ fun TelegramBot.startGettingOfUpdatesByLongPolling(
allowedUpdates: List<String>? = ALL_UPDATES_LIST, allowedUpdates: List<String>? = ALL_UPDATES_LIST,
autoDisableWebhooks: Boolean = true, autoDisableWebhooks: Boolean = true,
autoSkipTimeoutExceptions: Boolean = true, autoSkipTimeoutExceptions: Boolean = true,
mediaGroupsDebounceTimeMillis: Long? = 1000L,
updatesReceiver: UpdateReceiver<Update> updatesReceiver: UpdateReceiver<Update>
): Job = longPollingFlow( ): Job = longPollingFlow(
timeoutSeconds = timeoutSeconds, timeoutSeconds = timeoutSeconds,
exceptionsHandler = exceptionsHandler, exceptionsHandler = exceptionsHandler,
allowedUpdates = allowedUpdates, allowedUpdates = allowedUpdates,
autoDisableWebhooks = autoDisableWebhooks, autoDisableWebhooks = autoDisableWebhooks,
autoSkipTimeoutExceptions = autoSkipTimeoutExceptions autoSkipTimeoutExceptions = autoSkipTimeoutExceptions,
mediaGroupsDebounceTimeMillis = mediaGroupsDebounceTimeMillis
).subscribeSafely( ).subscribeSafely(
scope, scope,
exceptionsHandler ?: defaultSafelyExceptionHandler, exceptionsHandler ?: defaultSafelyExceptionHandler,
@@ -129,6 +158,10 @@ fun TelegramBot.startGettingOfUpdatesByLongPolling(
) )
/** /**
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
* retrieved in different updates
*
* @return [kotlinx.coroutines.flow.Flow] which will emit updates to the collector while they will be accumulated. Works * @return [kotlinx.coroutines.flow.Flow] which will emit updates to the collector while they will be accumulated. Works
* the same as [longPollingFlow], but it will cancel the flow after the first one [HttpRequestTimeoutException] * the same as [longPollingFlow], but it will cancel the flow after the first one [HttpRequestTimeoutException]
*/ */
@@ -137,7 +170,8 @@ fun TelegramBot.createAccumulatedUpdatesRetrieverFlow(
avoidCallbackQueries: Boolean = false, avoidCallbackQueries: Boolean = false,
exceptionsHandler: ExceptionHandler<Unit>? = null, exceptionsHandler: ExceptionHandler<Unit>? = null,
allowedUpdates: List<String>? = ALL_UPDATES_LIST, allowedUpdates: List<String>? = ALL_UPDATES_LIST,
autoDisableWebhooks: Boolean = true autoDisableWebhooks: Boolean = true,
mediaGroupsDebounceTimeMillis: Long? = 1000L,
): Flow<Update> = longPollingFlow( ): Flow<Update> = longPollingFlow(
timeoutSeconds = 0, timeoutSeconds = 0,
exceptionsHandler = { exceptionsHandler = {
@@ -149,11 +183,17 @@ fun TelegramBot.createAccumulatedUpdatesRetrieverFlow(
}, },
allowedUpdates = allowedUpdates, allowedUpdates = allowedUpdates,
autoDisableWebhooks = autoDisableWebhooks, autoDisableWebhooks = autoDisableWebhooks,
autoSkipTimeoutExceptions = false autoSkipTimeoutExceptions = false,
mediaGroupsDebounceTimeMillis = mediaGroupsDebounceTimeMillis
).filter { ).filter {
!(it is InlineQueryUpdate && avoidInlineQueries || it is CallbackQueryUpdate && avoidCallbackQueries) !(it is InlineQueryUpdate && avoidInlineQueries || it is CallbackQueryUpdate && avoidCallbackQueries)
} }
/**
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
* retrieved in different updates
*/
fun TelegramBot.retrieveAccumulatedUpdates( fun TelegramBot.retrieveAccumulatedUpdates(
avoidInlineQueries: Boolean = false, avoidInlineQueries: Boolean = false,
avoidCallbackQueries: Boolean = false, avoidCallbackQueries: Boolean = false,
@@ -161,25 +201,33 @@ fun TelegramBot.retrieveAccumulatedUpdates(
exceptionsHandler: (ExceptionHandler<Unit>)? = null, exceptionsHandler: (ExceptionHandler<Unit>)? = null,
allowedUpdates: List<String>? = ALL_UPDATES_LIST, allowedUpdates: List<String>? = ALL_UPDATES_LIST,
autoDisableWebhooks: Boolean = true, autoDisableWebhooks: Boolean = true,
mediaGroupsDebounceTimeMillis: Long? = 1000L,
updatesReceiver: UpdateReceiver<Update> updatesReceiver: UpdateReceiver<Update>
): Job = createAccumulatedUpdatesRetrieverFlow( ): Job = createAccumulatedUpdatesRetrieverFlow(
avoidInlineQueries, avoidInlineQueries,
avoidCallbackQueries, avoidCallbackQueries,
exceptionsHandler, exceptionsHandler,
allowedUpdates, allowedUpdates,
autoDisableWebhooks autoDisableWebhooks,
mediaGroupsDebounceTimeMillis
).subscribeSafelyWithoutExceptions( ).subscribeSafelyWithoutExceptions(
scope.LinkedSupervisorScope() scope.LinkedSupervisorScope()
) { ) {
updatesReceiver(it) updatesReceiver(it)
} }
/**
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
* retrieved in different updates
*/
fun TelegramBot.retrieveAccumulatedUpdates( fun TelegramBot.retrieveAccumulatedUpdates(
flowsUpdatesFilter: FlowsUpdatesFilter, flowsUpdatesFilter: FlowsUpdatesFilter,
avoidInlineQueries: Boolean = false, avoidInlineQueries: Boolean = false,
avoidCallbackQueries: Boolean = false, avoidCallbackQueries: Boolean = false,
scope: CoroutineScope = CoroutineScope(Dispatchers.Default), scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
autoDisableWebhooks: Boolean = true, autoDisableWebhooks: Boolean = true,
mediaGroupsDebounceTimeMillis: Long? = 1000L,
exceptionsHandler: ExceptionHandler<Unit>? = null exceptionsHandler: ExceptionHandler<Unit>? = null
) = retrieveAccumulatedUpdates( ) = retrieveAccumulatedUpdates(
avoidInlineQueries, avoidInlineQueries,
@@ -188,9 +236,15 @@ fun TelegramBot.retrieveAccumulatedUpdates(
exceptionsHandler, exceptionsHandler,
flowsUpdatesFilter.allowedUpdates, flowsUpdatesFilter.allowedUpdates,
autoDisableWebhooks, autoDisableWebhooks,
mediaGroupsDebounceTimeMillis,
flowsUpdatesFilter.asUpdateReceiver flowsUpdatesFilter.asUpdateReceiver
) )
/**
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
* retrieved in different updates
*/
suspend fun TelegramBot.flushAccumulatedUpdates( suspend fun TelegramBot.flushAccumulatedUpdates(
avoidInlineQueries: Boolean = false, avoidInlineQueries: Boolean = false,
avoidCallbackQueries: Boolean = false, avoidCallbackQueries: Boolean = false,
@@ -198,6 +252,7 @@ suspend fun TelegramBot.flushAccumulatedUpdates(
allowedUpdates: List<String>? = ALL_UPDATES_LIST, allowedUpdates: List<String>? = ALL_UPDATES_LIST,
exceptionsHandler: ExceptionHandler<Unit>? = null, exceptionsHandler: ExceptionHandler<Unit>? = null,
autoDisableWebhooks: Boolean = true, autoDisableWebhooks: Boolean = true,
mediaGroupsDebounceTimeMillis: Long? = 1000L,
updatesReceiver: UpdateReceiver<Update> = {} updatesReceiver: UpdateReceiver<Update> = {}
) = retrieveAccumulatedUpdates( ) = retrieveAccumulatedUpdates(
avoidInlineQueries, avoidInlineQueries,
@@ -206,12 +261,17 @@ suspend fun TelegramBot.flushAccumulatedUpdates(
exceptionsHandler, exceptionsHandler,
allowedUpdates, allowedUpdates,
autoDisableWebhooks, autoDisableWebhooks,
mediaGroupsDebounceTimeMillis,
updatesReceiver updatesReceiver
).join() ).join()
/** /**
* Will [startGettingOfUpdatesByLongPolling] using incoming [flowsUpdatesFilter]. It is assumed that you ALREADY CONFIGURE * Will [startGettingOfUpdatesByLongPolling] using incoming [updatesFilter]. It is assumed that you ALREADY CONFIGURE
* all updates receivers, because this method will trigger getting of updates and. * all updates receivers, because this method will trigger getting of updates and.
*
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
* retrieved in different updates
*/ */
fun TelegramBot.longPolling( fun TelegramBot.longPolling(
updatesFilter: UpdatesFilter, updatesFilter: UpdatesFilter,
@@ -219,6 +279,7 @@ fun TelegramBot.longPolling(
scope: CoroutineScope = CoroutineScope(Dispatchers.Default), scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
autoDisableWebhooks: Boolean = true, autoDisableWebhooks: Boolean = true,
autoSkipTimeoutExceptions: Boolean = true, autoSkipTimeoutExceptions: Boolean = true,
mediaGroupsDebounceTimeMillis: Long? = 1000L,
exceptionsHandler: ExceptionHandler<Unit>? = null exceptionsHandler: ExceptionHandler<Unit>? = null
): Job = updatesFilter.run { ): Job = updatesFilter.run {
startGettingOfUpdatesByLongPolling( startGettingOfUpdatesByLongPolling(
@@ -228,6 +289,7 @@ fun TelegramBot.longPolling(
allowedUpdates = allowedUpdates, allowedUpdates = allowedUpdates,
autoDisableWebhooks = autoDisableWebhooks, autoDisableWebhooks = autoDisableWebhooks,
autoSkipTimeoutExceptions = autoSkipTimeoutExceptions, autoSkipTimeoutExceptions = autoSkipTimeoutExceptions,
mediaGroupsDebounceTimeMillis = mediaGroupsDebounceTimeMillis,
updatesReceiver = asUpdateReceiver updatesReceiver = asUpdateReceiver
) )
} }
@@ -236,6 +298,10 @@ fun TelegramBot.longPolling(
* Will enable [longPolling] by creating [FlowsUpdatesFilter] with [flowsUpdatesFilterUpdatesKeeperCount] as an argument * Will enable [longPolling] by creating [FlowsUpdatesFilter] with [flowsUpdatesFilterUpdatesKeeperCount] as an argument
* and applied [flowUpdatesPreset]. It is assumed that you WILL CONFIGURE all updates receivers in [flowUpdatesPreset], * and applied [flowUpdatesPreset]. It is assumed that you WILL CONFIGURE all updates receivers in [flowUpdatesPreset],
* because of after [flowUpdatesPreset] method calling will be triggered getting of updates. * because of after [flowUpdatesPreset] method calling will be triggered getting of updates.
*
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
* retrieved in different updates
*/ */
@Suppress("unused") @Suppress("unused")
fun TelegramBot.longPolling( fun TelegramBot.longPolling(
@@ -245,15 +311,22 @@ fun TelegramBot.longPolling(
flowsUpdatesFilterUpdatesKeeperCount: Int = 100, flowsUpdatesFilterUpdatesKeeperCount: Int = 100,
autoDisableWebhooks: Boolean = true, autoDisableWebhooks: Boolean = true,
autoSkipTimeoutExceptions: Boolean = true, autoSkipTimeoutExceptions: Boolean = true,
mediaGroupsDebounceTimeMillis: Long? = 1000L,
flowUpdatesPreset: FlowsUpdatesFilter.() -> Unit flowUpdatesPreset: FlowsUpdatesFilter.() -> Unit
): Job = longPolling(FlowsUpdatesFilter(flowsUpdatesFilterUpdatesKeeperCount).apply(flowUpdatesPreset), timeoutSeconds, scope, autoDisableWebhooks, autoSkipTimeoutExceptions, exceptionsHandler) ): Job = longPolling(FlowsUpdatesFilter(flowsUpdatesFilterUpdatesKeeperCount).apply(flowUpdatesPreset), timeoutSeconds, scope, autoDisableWebhooks, autoSkipTimeoutExceptions, mediaGroupsDebounceTimeMillis, exceptionsHandler)
/**
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
* retrieved in different updates
*/
fun RequestsExecutor.startGettingOfUpdatesByLongPolling( fun RequestsExecutor.startGettingOfUpdatesByLongPolling(
updatesFilter: UpdatesFilter, updatesFilter: UpdatesFilter,
timeoutSeconds: Seconds = 30, timeoutSeconds: Seconds = 30,
exceptionsHandler: ExceptionHandler<Unit>? = null, exceptionsHandler: ExceptionHandler<Unit>? = null,
scope: CoroutineScope = CoroutineScope(Dispatchers.Default), scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
autoDisableWebhooks: Boolean = true, autoDisableWebhooks: Boolean = true,
mediaGroupsDebounceTimeMillis: Long? = 1000L,
autoSkipTimeoutExceptions: Boolean = true, autoSkipTimeoutExceptions: Boolean = true,
): Job = startGettingOfUpdatesByLongPolling( ): Job = startGettingOfUpdatesByLongPolling(
timeoutSeconds, timeoutSeconds,
@@ -262,5 +335,6 @@ fun RequestsExecutor.startGettingOfUpdatesByLongPolling(
updatesFilter.allowedUpdates, updatesFilter.allowedUpdates,
autoDisableWebhooks, autoDisableWebhooks,
autoSkipTimeoutExceptions, autoSkipTimeoutExceptions,
mediaGroupsDebounceTimeMillis,
updatesFilter.asUpdateReceiver updatesFilter.asUpdateReceiver
) )

View File

@@ -1,6 +1,5 @@
package dev.inmo.tgbotapi.extensions.utils.updates.retrieving package dev.inmo.tgbotapi.extensions.utils.updates.retrieving
import dev.inmo.micro_utils.coroutines.launchSafely
import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions
import dev.inmo.tgbotapi.extensions.utils.updates.convertWithMediaGroupUpdates import dev.inmo.tgbotapi.extensions.utils.updates.convertWithMediaGroupUpdates
import dev.inmo.tgbotapi.types.message.abstracts.PossiblyMediaGroupMessage import dev.inmo.tgbotapi.types.message.abstracts.PossiblyMediaGroupMessage
@@ -12,7 +11,6 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
/** /**
* Create [UpdateReceiver] object which will correctly accumulate updates and send into output updates which INCLUDE * Create [UpdateReceiver] object which will correctly accumulate updates and send into output updates which INCLUDE
* [dev.inmo.tgbotapi.types.update.MediaGroupUpdates.MediaGroupUpdate]s. * [dev.inmo.tgbotapi.types.update.MediaGroupUpdates.MediaGroupUpdate]s.

View File

@@ -26,6 +26,9 @@ import java.util.concurrent.Executors
* @param [scope] Will be used for mapping of media groups * @param [scope] Will be used for mapping of media groups
* @param [exceptionsHandler] Pass this parameter to set custom exception handler for getting updates * @param [exceptionsHandler] Pass this parameter to set custom exception handler for getting updates
* @param [block] Some receiver block like [dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter] * @param [block] Some receiver block like [dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter]
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
* retrieved in different updates
* *
* @see dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter * @see dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
* @see UpdatesFilter * @see UpdatesFilter
@@ -57,6 +60,11 @@ fun Route.includeWebhookHandlingInRoute(
} }
} }
/**
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
* retrieved in different updates
*/
fun Route.includeWebhookHandlingInRouteWithFlows( fun Route.includeWebhookHandlingInRouteWithFlows(
scope: CoroutineScope, scope: CoroutineScope,
exceptionsHandler: ExceptionHandler<Unit>? = null, exceptionsHandler: ExceptionHandler<Unit>? = null,
@@ -76,6 +84,9 @@ fun Route.includeWebhookHandlingInRouteWithFlows(
* @param listenRoute address to listen by bot. If null - will be set up in root of host * @param listenRoute address to listen by bot. If null - will be set up in root of host
* @param scope Scope which will be used for * @param scope Scope which will be used for
* @param privateKeyConfig If configured - server will be created with [sslConnector]. [connector] will be used otherwise * @param privateKeyConfig If configured - server will be created with [sslConnector]. [connector] will be used otherwise
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
* retrieved in different updates
* *
* @see dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter * @see dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
* @see UpdatesFilter * @see UpdatesFilter
@@ -132,6 +143,9 @@ fun startListenWebhooks(
* @param listenPort port which will be listen by bot * @param listenPort port which will be listen by bot
* @param listenRoute address to listen by bot * @param listenRoute address to listen by bot
* @param scope Scope which will be used for * @param scope Scope which will be used for
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
* retrieved in different updates
* *
* @see dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter * @see dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
* @see UpdatesFilter * @see UpdatesFilter

View File

@@ -1,6 +1,7 @@
plugins { plugins {
id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization" id "org.jetbrains.kotlin.plugin.serialization"
id "org.jetbrains.dokka"
} }
project.description = "Web App bindings for the Telegram Web Apps API" project.description = "Web App bindings for the Telegram Web Apps API"

View File

@@ -1,6 +1,7 @@
plugins { plugins {
id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization" id "org.jetbrains.kotlin.plugin.serialization"
id "org.jetbrains.dokka"
} }
project.description = "Full collection of all built-in tgbotapi tools" project.description = "Full collection of all built-in tgbotapi tools"