1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2025-11-16 12:00:18 +00:00

Compare commits

..

46 Commits

Author SHA1 Message Date
cf3d07a20d update microutils and fill changelog 2023-01-18 23:44:39 +06:00
e40548e558 fix of return type in SendMediaGroup and fill changelog 2023-01-14 22:09:27 +06:00
4cd8e823c6 Update libs.versions.toml 2023-01-14 09:19:53 +06:00
9c7faec124 Merge pull request #707 from madhead/bugfix/SetChatAdministratorCustomTitle.serializer()
Fix the `requestSerializer` for `SetChatAdministratorCustomTitle`
2023-01-14 09:18:36 +06:00
2856880a6e start 5.0.1 2023-01-14 09:16:04 +06:00
madhead
5445fdbfa5 Fix the requestSerializer for SetChatAdministratorCustomTitle 2023-01-14 00:26:49 +01:00
ba53d0c75d Update CHANGELOG.md 2022-12-31 16:23:24 +06:00
78f6cc5a97 Update README.md 2022-12-31 16:22:57 +06:00
6ab7c6f9d9 Update CHANGELOG.md 2022-12-31 16:21:49 +06:00
cb6b33727e Merge pull request #704 from InsanusMokrassar/5.0.0
5.0.0
2022-12-31 16:04:38 +06:00
bc4a2235c5 add opportunity in long polling to automatically delete webhook 2022-12-31 15:23:14 +06:00
300f94fd48 fixes 2022-12-31 15:23:14 +06:00
40617ad9c8 add support of Bot API 6.5 web apps 2022-12-31 15:23:14 +06:00
bea056bba3 add full support of editGeneralForumTopic, closeGeneralForumTopic, reopenGeneralForumTopic, hideGeneralForumTopic, unhideGeneralForumTopic 2022-12-31 15:23:14 +06:00
9a33451f88 add support of forum_topic_edited, general_forum_topic_hidden, general_forum_topic_unhidden, and write_access_allowed 2022-12-31 15:23:14 +06:00
c4659b558f add support of has_aggressive_anti_spam_enabled 2022-12-31 15:23:14 +06:00
5a30a07554 add support of has_hidden_members 2022-12-31 15:23:14 +06:00
b064becb8a add support of topics for actions 2022-12-31 15:23:14 +06:00
463d5252bd editForumtTopic optional fields 2022-12-31 15:23:14 +06:00
8b5da90e28 add spoilered in telegrammedia 2022-12-31 15:23:14 +06:00
febd6ce63c support of has_media_spoiler in message and sendPhoto/sendVideo/sendAnimation 2022-12-31 15:23:14 +06:00
8df8b87d54 add ReplyKeyboardMarkup 2022-12-31 15:23:14 +06:00
c882717bcc start 5.0.0 2022-12-31 15:23:14 +06:00
4aa5924615 Update CHANGELOG.md 2022-12-31 15:17:21 +06:00
2b8e728559 fixes in updateHandlerWithMediaGroupsAdaptation 2022-12-31 15:17:21 +06:00
90ad34f114 Update BehaviourContextWithFSM.kt 2022-12-31 15:17:21 +06:00
dbe2607994 Update BehaviourContextWithFSM.kt 2022-12-31 15:17:21 +06:00
692b668f92 fixes and improvements 2022-12-31 15:17:21 +06:00
f2322e3e57 Fixes in DefaultBehaviourContextWithFSM 2022-12-31 15:17:21 +06:00
ae002ead43 start 4.2.4 2022-12-31 15:17:21 +06:00
4197e13c54 Update CHANGELOG.md 2022-12-28 09:12:54 +06:00
e09ea9a9b4 upfill changelog 2022-12-28 09:11:49 +06:00
2a32654d57 update miroutils and fill changelog 2022-12-28 09:05:32 +06:00
0fff553ce1 Update KtorRequestsExecutor.kt 2022-12-27 22:31:42 +06:00
33a1701f5b Update ExceptionsOnlyLimiter.kt 2022-12-27 22:30:47 +06:00
f9a9f958ba Update ExceptionsOnlyLimiter.kt 2022-12-27 22:25:26 +06:00
f686be0271 Update ExceptionsOnlyLimiter.kt 2022-12-27 22:22:03 +06:00
91307f3ebf improvements in ExceptionsOnlyLimiter 2022-12-26 21:37:48 +06:00
8e64205f53 several improvements in requests limiters 2022-12-26 20:49:29 +06:00
5434df1f02 Merge pull request #695 from InsanusMokrassar/4.2.2
4.2.2
2022-12-18 10:05:17 +06:00
e56199ac9f Update CHANGELOG.md 2022-12-18 10:01:46 +06:00
3e199c6944 Update libs.versions.toml 2022-12-18 10:01:25 +06:00
b43d9aefb9 fix of #694 2022-12-13 10:52:56 +06:00
fe133bbde0 update microutils 2022-12-13 10:49:18 +06:00
332fe95adf start 4.2.2 2022-12-13 10:48:38 +06:00
1f416d4a28 Merge pull request #693 from InsanusMokrassar/4.2.1
4.2.1
2022-12-08 10:50:07 +06:00
74 changed files with 1077 additions and 290 deletions

View File

@@ -1,5 +1,41 @@
# TelegramBotAPI changelog
## 5.0.1
* `Versions`:
* `MicroUtils`: `0.16.4` -> `0.16.6`
* `Ktor`: `2.2.1` -> `2.2.2`
* `Core`:
* Fixes in `SendMediaGroup` request
* Fixes in `SetChatAdministratorCustomTitle` request (thanks to [@madhead](https://github.com/madhead))
## 5.0.0
[Bot API 6.4](https://core.telegram.org/bots/api-changelog#december-30-2022) support!
* Long-polling improvements
## 4.2.4
* `Core`:
* Fixes in webhook parts adapter
* `BehaviourBuilderWithFSM`:
* Fixes in `DefaultBehaviourContextWithFSM`
## 4.2.3
* `Versions`:
* `MicroUtils`: `0.16.2` -> `0.16.4`
* `Core`:
* Simplify default `RequestsLimiter` (`ExceptionsOnlyLimiter`) (thanks to [@y9san9](https://github.com/y9san9) for help)
## 4.2.2
* `Versions`:
* `MicroUtils`: `0.16.0` -> `0.16.2`
* `Core`:
* Fix of [#694](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/694): add opportunity to create `ChatId` and `ChatIdWithThreadId` from `IdChatIdentifier`
## 4.2.1
* `Versions`:

View File

@@ -1,4 +1,4 @@
# TelegramBotAPI [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi) [![Supported version](https://img.shields.io/badge/Telegram%20Bot%20API-6.3-blue)](https://core.telegram.org/bots/api-changelog#november-5-2022)
# TelegramBotAPI [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi) [![Supported version](https://img.shields.io/badge/Telegram%20Bot%20API-6.4-blue)](https://core.telegram.org/bots/api-changelog#december-30-2022)
| Docs | [![KDocs](https://img.shields.io/static/v1?label=Dokka&message=KDocs&color=blue&logo=kotlin)](https://tgbotapi.inmo.dev/index.html) [![Mini tutorial](https://img.shields.io/static/v1?label=Bookstack&message=Tutorial&color=blue&logo=bookstack)](https://bookstack.inmo.dev/books/telegrambotapi/chapter/introduction-tutorial) |
|:---:|:---:|

View File

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

View File

@@ -8,12 +8,12 @@ javax-activation = "1.1.1"
korlibs = "3.4.0"
uuid = "0.6.0"
ktor = "2.2.1"
ktor = "2.2.2"
ksp = "1.7.22-1.0.8"
kotlin-poet = "1.12.0"
microutils = "0.16.0"
microutils = "0.16.6"
github-release-plugin = "2.4.1"
dokka = "1.7.20"

View File

@@ -0,0 +1,19 @@
package dev.inmo.tgbotapi.extensions.api.chat.forum
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.chat.forum.CloseForumTopic
import dev.inmo.tgbotapi.requests.chat.forum.CloseGeneralForumTopic
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.ForumTopic
import dev.inmo.tgbotapi.types.MessageThreadId
import dev.inmo.tgbotapi.types.chat.Chat
suspend fun TelegramBot.closeGeneralForumTopic(
chatId: ChatIdentifier
) = execute(
CloseGeneralForumTopic(chatId)
)
suspend fun TelegramBot.closeGeneralForumTopic(
chat: Chat
) = closeGeneralForumTopic(chat.id)

View File

@@ -11,8 +11,8 @@ import dev.inmo.tgbotapi.types.chat.Chat
suspend fun TelegramBot.editForumTopic(
chatId: ChatIdentifier,
messageThreadId: MessageThreadId,
name: String,
iconEmojiId: CustomEmojiId
name: String? = null,
iconEmojiId: CustomEmojiId? = null
) = execute(
EditForumTopic(
chatId,
@@ -25,12 +25,12 @@ suspend fun TelegramBot.editForumTopic(
suspend fun TelegramBot.editForumTopic(
chat: Chat,
messageThreadId: MessageThreadId,
name: String,
iconEmojiId: CustomEmojiId
name: String? = null,
iconEmojiId: CustomEmojiId? = null
) = editForumTopic(chat.id, messageThreadId, name, iconEmojiId)
suspend fun TelegramBot.editForumTopic(
chatIdentifier: ChatIdentifier,
forumTopic: ForumTopic,
iconEmojiId: CustomEmojiId = forumTopic.iconEmojiId ?: error("Icon emoji id in forum topic should be presented when edit forum topic basing on other forum topic object")
iconEmojiId: CustomEmojiId? = forumTopic.iconEmojiId
) = editForumTopic(chatIdentifier, forumTopic.messageThreadId, forumTopic.name, iconEmojiId)

View File

@@ -0,0 +1,30 @@
package dev.inmo.tgbotapi.extensions.api.chat.forum
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.chat.forum.EditForumTopic
import dev.inmo.tgbotapi.requests.chat.forum.EditGeneralForumTopic
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.CustomEmojiId
import dev.inmo.tgbotapi.types.ForumTopic
import dev.inmo.tgbotapi.types.MessageThreadId
import dev.inmo.tgbotapi.types.chat.Chat
suspend fun TelegramBot.editGeneralForumTopic(
chatId: ChatIdentifier,
name: String
) = execute(
EditGeneralForumTopic(
chatId,
name
)
)
suspend fun TelegramBot.editGeneralForumTopic(
chat: Chat,
name: String
) = editGeneralForumTopic(chat.id, name)
suspend fun TelegramBot.editGeneralForumTopic(
chatIdentifier: ChatIdentifier,
forumTopic: ForumTopic,
) = editGeneralForumTopic(chatIdentifier, forumTopic.name)

View File

@@ -0,0 +1,20 @@
package dev.inmo.tgbotapi.extensions.api.chat.forum
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.chat.forum.CloseForumTopic
import dev.inmo.tgbotapi.requests.chat.forum.CloseGeneralForumTopic
import dev.inmo.tgbotapi.requests.chat.forum.HideGeneralForumTopic
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.ForumTopic
import dev.inmo.tgbotapi.types.MessageThreadId
import dev.inmo.tgbotapi.types.chat.Chat
suspend fun TelegramBot.hideGeneralForumTopic(
chatId: ChatIdentifier
) = execute(
HideGeneralForumTopic(chatId)
)
suspend fun TelegramBot.hideGeneralForumTopic(
chat: Chat
) = hideGeneralForumTopic(chat.id)

View File

@@ -0,0 +1,19 @@
package dev.inmo.tgbotapi.extensions.api.chat.forum
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.chat.forum.ReopenForumTopic
import dev.inmo.tgbotapi.requests.chat.forum.ReopenGeneralForumTopic
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.ForumTopic
import dev.inmo.tgbotapi.types.MessageThreadId
import dev.inmo.tgbotapi.types.chat.Chat
suspend fun TelegramBot.reopenGeneralForumTopic(
chatId: ChatIdentifier
) = execute(
ReopenGeneralForumTopic(chatId)
)
suspend fun TelegramBot.reopenGeneralForumTopic(
chat: Chat
) = reopenGeneralForumTopic(chat.id)

View File

@@ -0,0 +1,21 @@
package dev.inmo.tgbotapi.extensions.api.chat.forum
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.chat.forum.CloseForumTopic
import dev.inmo.tgbotapi.requests.chat.forum.CloseGeneralForumTopic
import dev.inmo.tgbotapi.requests.chat.forum.HideGeneralForumTopic
import dev.inmo.tgbotapi.requests.chat.forum.UnhideGeneralForumTopic
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.ForumTopic
import dev.inmo.tgbotapi.types.MessageThreadId
import dev.inmo.tgbotapi.types.chat.Chat
suspend fun TelegramBot.unhideGeneralForumTopic(
chatId: ChatIdentifier
) = execute(
UnhideGeneralForumTopic(chatId)
)
suspend fun TelegramBot.unhideGeneralForumTopic(
chat: Chat
) = unhideGeneralForumTopic(chat.id)

View File

@@ -379,6 +379,7 @@ suspend inline fun TelegramBot.replyWithAnimation(
thumb: InputFile? = null,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -392,6 +393,7 @@ suspend inline fun TelegramBot.replyWithAnimation(
thumb,
text,
parseMode,
spoilered,
duration,
width,
height,
@@ -408,6 +410,7 @@ suspend inline fun TelegramBot.reply(
animation: AnimationFile,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -415,12 +418,13 @@ suspend inline fun TelegramBot.reply(
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendAnimation(to.chat, animation, text, parseMode, duration, width, height, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
) = sendAnimation(to.chat, animation, text, parseMode, spoilered, duration, width, height, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.replyWithAnimation(
to: Message,
animation: InputFile,
entities: TextSourcesList,
spoilered: Boolean = false,
thumb: InputFile? = null,
duration: Long? = null,
width: Int? = null,
@@ -434,6 +438,7 @@ suspend inline fun TelegramBot.replyWithAnimation(
animation,
thumb,
entities,
spoilered,
duration,
width,
height,
@@ -449,6 +454,7 @@ suspend inline fun TelegramBot.reply(
to: Message,
animation: AnimationFile,
entities: TextSourcesList,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -456,7 +462,7 @@ suspend inline fun TelegramBot.reply(
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendAnimation(to.chat, animation, entities, duration, width, height, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
) = sendAnimation(to.chat, animation, entities, spoilered, duration, width, height, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
// Audio
@@ -608,64 +614,70 @@ suspend inline fun TelegramBot.replyWithPhoto(
fileId: InputFile,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(to.chat, fileId, text, parseMode, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(to.chat, fileId, text, parseMode, spoilered, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.reply(
to: Message,
photo: Photo,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(to.chat, photo, text, parseMode, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(to.chat, photo, text, parseMode, spoilered, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.reply(
to: Message,
photoSize: PhotoSize,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(to.chat, photoSize, text, parseMode, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(to.chat, photoSize, text, parseMode, spoilered, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.replyWithPhoto(
to: Message,
fileId: InputFile,
entities: TextSourcesList,
spoilered: Boolean = false,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(to.chat, fileId, entities, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(to.chat, fileId, entities, spoilered, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.reply(
to: Message,
photo: Photo,
entities: TextSourcesList,
spoilered: Boolean = false,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(to.chat, photo, entities, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(to.chat, photo, entities, spoilered, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.reply(
to: Message,
photoSize: PhotoSize,
entities: TextSourcesList,
spoilered: Boolean = false,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(to.chat, photoSize, entities, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(to.chat, photoSize, entities, spoilered, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
// Sticker
@@ -697,6 +709,7 @@ suspend inline fun TelegramBot.replyWithVideo(
thumb: InputFile? = null,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -704,24 +717,26 @@ suspend inline fun TelegramBot.replyWithVideo(
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendVideo(to.chat, video, thumb, text, parseMode, duration, width, height, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
) = sendVideo(to.chat, video, thumb, text, parseMode, spoilered, duration, width, height, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.reply(
to: Message,
video: VideoFile,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendVideo(to.chat, video, text, parseMode, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
) = sendVideo(to.chat, video, text, parseMode, spoilered, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.replyWithVideo(
to: Message,
video: InputFile,
thumb: InputFile? = null,
entities: TextSourcesList,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -729,17 +744,18 @@ suspend inline fun TelegramBot.replyWithVideo(
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendVideo(to.chat, video, thumb, entities, duration, width, height, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
) = sendVideo(to.chat, video, thumb, entities, spoilered, duration, width, height, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.reply(
to: Message,
video: VideoFile,
entities: TextSourcesList,
spoilered: Boolean = false,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendVideo(to.chat, video, entities, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
) = sendVideo(to.chat, video, entities, spoilered, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
// VideoNotes

View File

@@ -410,6 +410,7 @@ suspend inline fun TelegramBot.replyWithAnimation(
thumb: InputFile? = null,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -424,6 +425,7 @@ suspend inline fun TelegramBot.replyWithAnimation(
thumb,
text,
parseMode,
spoilered,
duration,
width,
height,
@@ -441,6 +443,7 @@ suspend inline fun TelegramBot.reply(
animation: AnimationFile,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -449,13 +452,14 @@ suspend inline fun TelegramBot.reply(
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendAnimation(toChatId, animation, text, parseMode, duration, width, height, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
) = sendAnimation(toChatId, animation, text, parseMode, spoilered, duration, width, height, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.replyWithAnimation(
toChatId: IdChatIdentifier,
toMessageId: MessageId,
animation: InputFile,
entities: TextSourcesList,
spoilered: Boolean = false,
thumb: InputFile? = null,
duration: Long? = null,
width: Int? = null,
@@ -470,6 +474,7 @@ suspend inline fun TelegramBot.replyWithAnimation(
animation,
thumb,
entities,
spoilered,
duration,
width,
height,
@@ -486,6 +491,7 @@ suspend inline fun TelegramBot.reply(
toMessageId: MessageId,
animation: AnimationFile,
entities: TextSourcesList,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -494,7 +500,7 @@ suspend inline fun TelegramBot.reply(
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendAnimation(toChatId, animation, entities, duration, width, height, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
) = sendAnimation(toChatId, animation, entities, spoilered, duration, width, height, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
// Audio
@@ -671,12 +677,13 @@ suspend inline fun TelegramBot.replyWithPhoto(
fileId: InputFile,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
threadId: MessageThreadId? = toChatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(toChatId, fileId, text, parseMode, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(toChatId, fileId, text, parseMode, spoilered, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.reply(
toChatId: IdChatIdentifier,
@@ -684,12 +691,13 @@ suspend inline fun TelegramBot.reply(
photo: Photo,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
threadId: MessageThreadId? = toChatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(toChatId, photo, text, parseMode, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(toChatId, photo, text, parseMode, spoilered, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.reply(
toChatId: IdChatIdentifier,
@@ -697,12 +705,13 @@ suspend inline fun TelegramBot.reply(
photoSize: PhotoSize,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
threadId: MessageThreadId? = toChatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(toChatId, photoSize, text, parseMode, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(toChatId, photoSize, text, parseMode, spoilered, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.replyWithPhoto(
@@ -710,36 +719,39 @@ suspend inline fun TelegramBot.replyWithPhoto(
toMessageId: MessageId,
fileId: InputFile,
entities: TextSourcesList,
spoilered: Boolean = false,
threadId: MessageThreadId? = toChatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(toChatId, fileId, entities, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(toChatId, fileId, entities, spoilered, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.reply(
toChatId: IdChatIdentifier,
toMessageId: MessageId,
photo: Photo,
entities: TextSourcesList,
spoilered: Boolean = false,
threadId: MessageThreadId? = toChatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(toChatId, photo, entities, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(toChatId, photo, entities, spoilered, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.reply(
toChatId: IdChatIdentifier,
toMessageId: MessageId,
photoSize: PhotoSize,
entities: TextSourcesList,
spoilered: Boolean = false,
threadId: MessageThreadId? = toChatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(toChatId, photoSize, entities, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(toChatId, photoSize, entities, spoilered, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
// Sticker
@@ -776,6 +788,7 @@ suspend inline fun TelegramBot.replyWithVideo(
thumb: InputFile? = null,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -784,7 +797,7 @@ suspend inline fun TelegramBot.replyWithVideo(
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendVideo(toChatId, video, thumb, text, parseMode, duration, width, height, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
) = sendVideo(toChatId, video, thumb, text, parseMode, spoilered, duration, width, height, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.reply(
toChatId: IdChatIdentifier,
@@ -792,12 +805,13 @@ suspend inline fun TelegramBot.reply(
video: VideoFile,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
threadId: MessageThreadId? = toChatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendVideo(toChatId, video, text, parseMode, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
) = sendVideo(toChatId, video, text, parseMode, spoilered, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.replyWithVideo(
toChatId: IdChatIdentifier,
@@ -805,6 +819,7 @@ suspend inline fun TelegramBot.replyWithVideo(
video: InputFile,
thumb: InputFile? = null,
entities: TextSourcesList,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -813,19 +828,20 @@ suspend inline fun TelegramBot.replyWithVideo(
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendVideo(toChatId, video, thumb, entities, duration, width, height, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
) = sendVideo(toChatId, video, thumb, entities, spoilered, duration, width, height, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.reply(
toChatId: IdChatIdentifier,
toMessageId: MessageId,
video: VideoFile,
entities: TextSourcesList,
spoilered: Boolean = false,
threadId: MessageThreadId? = toChatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendVideo(toChatId, video, entities, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
) = sendVideo(toChatId, video, entities, spoilered, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
// VideoNotes

View File

@@ -3,104 +3,129 @@ package dev.inmo.tgbotapi.extensions.api.send
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.send.SendAction
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.MessageThreadId
import dev.inmo.tgbotapi.types.actions.*
import dev.inmo.tgbotapi.types.chat.Chat
import dev.inmo.tgbotapi.types.threadId
suspend fun TelegramBot.sendBotAction(
chatId: ChatIdentifier,
action: BotAction
action: BotAction,
threadId: MessageThreadId? = chatId.threadId
) = execute(
SendAction(chatId, action)
SendAction(chatId, action, threadId)
)
suspend fun TelegramBot.sendBotAction(
chat: Chat,
action: BotAction
) = sendBotAction(chat.id, action)
action: BotAction,
threadId: MessageThreadId? = chat.id.threadId
) = sendBotAction(chat.id, action, threadId)
suspend fun TelegramBot.sendActionTyping(
chatId: ChatIdentifier
) = sendBotAction(chatId, TypingAction)
chatId: ChatIdentifier,
threadId: MessageThreadId? = chatId.threadId
) = sendBotAction(chatId, TypingAction, threadId)
suspend fun TelegramBot.sendActionUploadPhoto(
chatId: ChatIdentifier
) = sendBotAction(chatId, UploadPhotoAction)
chatId: ChatIdentifier,
threadId: MessageThreadId? = chatId.threadId
) = sendBotAction(chatId, UploadPhotoAction, threadId)
suspend fun TelegramBot.sendActionRecordVideo(
chatId: ChatIdentifier
) = sendBotAction(chatId, RecordVideoAction)
chatId: ChatIdentifier,
threadId: MessageThreadId? = chatId.threadId
) = sendBotAction(chatId, RecordVideoAction, threadId)
suspend fun TelegramBot.sendActionUploadVideo(
chatId: ChatIdentifier
) = sendBotAction(chatId, UploadVideoAction)
chatId: ChatIdentifier,
threadId: MessageThreadId? = chatId.threadId
) = sendBotAction(chatId, UploadVideoAction, threadId)
suspend fun TelegramBot.sendActionRecordVoice(
chatId: ChatIdentifier
) = sendBotAction(chatId, RecordVoiceAction)
chatId: ChatIdentifier,
threadId: MessageThreadId? = chatId.threadId
) = sendBotAction(chatId, RecordVoiceAction, threadId)
suspend fun TelegramBot.sendActionUploadVoice(
chatId: ChatIdentifier
) = sendBotAction(chatId, UploadVoiceAction)
chatId: ChatIdentifier,
threadId: MessageThreadId? = chatId.threadId
) = sendBotAction(chatId, UploadVoiceAction, threadId)
suspend fun TelegramBot.sendActionUploadDocument(
chatId: ChatIdentifier
) = sendBotAction(chatId, UploadDocumentAction)
chatId: ChatIdentifier,
threadId: MessageThreadId? = chatId.threadId
) = sendBotAction(chatId, UploadDocumentAction, threadId)
suspend fun TelegramBot.sendActionFindLocation(
chatId: ChatIdentifier
) = sendBotAction(chatId, FindLocationAction)
chatId: ChatIdentifier,
threadId: MessageThreadId? = chatId.threadId
) = sendBotAction(chatId, FindLocationAction, threadId)
suspend fun TelegramBot.sendActionRecordVideoNote(
chatId: ChatIdentifier
) = sendBotAction(chatId, RecordVideoNoteAction)
chatId: ChatIdentifier,
threadId: MessageThreadId? = chatId.threadId
) = sendBotAction(chatId, RecordVideoNoteAction, threadId)
suspend fun TelegramBot.sendActionUploadVideoNote(
chatId: ChatIdentifier
) = sendBotAction(chatId, UploadVideoNoteAction)
chatId: ChatIdentifier,
threadId: MessageThreadId? = chatId.threadId
) = sendBotAction(chatId, UploadVideoNoteAction, threadId)
suspend fun TelegramBot.sendActionTyping(
chat: Chat
) = sendBotAction(chat, TypingAction)
chat: Chat,
threadId: MessageThreadId? = chat.id.threadId
) = sendBotAction(chat, TypingAction, threadId)
suspend fun TelegramBot.sendActionUploadPhoto(
chat: Chat
) = sendBotAction(chat, UploadPhotoAction)
chat: Chat,
threadId: MessageThreadId? = chat.id.threadId
) = sendBotAction(chat, UploadPhotoAction, threadId)
suspend fun TelegramBot.sendActionRecordVideo(
chat: Chat
) = sendBotAction(chat, RecordVideoAction)
chat: Chat,
threadId: MessageThreadId? = chat.id.threadId
) = sendBotAction(chat, RecordVideoAction, threadId)
suspend fun TelegramBot.sendActionUploadVideo(
chat: Chat
) = sendBotAction(chat, UploadVideoAction)
chat: Chat,
threadId: MessageThreadId? = chat.id.threadId
) = sendBotAction(chat, UploadVideoAction, threadId)
suspend fun TelegramBot.sendActionRecordVoice(
chat: Chat
) = sendBotAction(chat, RecordVoiceAction)
chat: Chat,
threadId: MessageThreadId? = chat.id.threadId
) = sendBotAction(chat, RecordVoiceAction, threadId)
suspend fun TelegramBot.sendActionUploadVoice(
chat: Chat
) = sendBotAction(chat, UploadVoiceAction)
chat: Chat,
threadId: MessageThreadId? = chat.id.threadId
) = sendBotAction(chat, UploadVoiceAction, threadId)
suspend fun TelegramBot.sendActionUploadDocument(
chat: Chat
) = sendBotAction(chat, UploadDocumentAction)
chat: Chat,
threadId: MessageThreadId? = chat.id.threadId
) = sendBotAction(chat, UploadDocumentAction, threadId)
suspend fun TelegramBot.sendActionFindLocation(
chat: Chat
) = sendBotAction(chat, FindLocationAction)
chat: Chat,
threadId: MessageThreadId? = chat.id.threadId
) = sendBotAction(chat, FindLocationAction, threadId)
suspend fun TelegramBot.sendActionRecordVideoNote(
chat: Chat
) = sendBotAction(chat, RecordVideoNoteAction)
chat: Chat,
threadId: MessageThreadId? = chat.id.threadId
) = sendBotAction(chat, RecordVideoNoteAction, threadId)
suspend fun TelegramBot.sendActionUploadVideoNote(
chat: Chat
) = sendBotAction(chat, UploadVideoNoteAction)
chat: Chat,
threadId: MessageThreadId? = chat.id.threadId
) = sendBotAction(chat, UploadVideoNoteAction, threadId)
suspend fun TelegramBot.sendActionChooseStickerAction(
chat: Chat
) = sendBotAction(chat, ChooseStickerAction)
chat: Chat,
threadId: MessageThreadId? = chat.id.threadId
) = sendBotAction(chat, ChooseStickerAction, threadId)

View File

@@ -38,13 +38,14 @@ suspend fun <T> TelegramBot.withAction(
suspend fun <T> TelegramBot.withAction(
chatId: IdChatIdentifier,
action: BotAction,
threadId: MessageThreadId? = chatId.threadId,
block: TelegramBotActionCallback<T>
): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return withAction(
SendAction(chatId, action),
SendAction(chatId, action, threadId),
block
)
}
@@ -53,6 +54,7 @@ suspend fun <T> TelegramBot.withAction(
suspend fun <T> TelegramBot.withAction(
chat: Chat,
action: BotAction,
threadId: MessageThreadId? = chat.id.threadId,
block: TelegramBotActionCallback<T>
): T {
contract {
@@ -61,163 +63,164 @@ suspend fun <T> TelegramBot.withAction(
return withAction(
chat.id,
action,
threadId,
block
)
}
@OptIn(ExperimentalContracts::class)
suspend fun <T> TelegramBot.withTypingAction(chatId: IdChatIdentifier, block: TelegramBotActionCallback<T>) : T {
suspend fun <T> TelegramBot.withTypingAction(chatId: IdChatIdentifier, threadId: MessageThreadId? = chatId.threadId,block: TelegramBotActionCallback<T>) : T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return withAction(chatId, TypingAction, block)
return withAction(chatId, TypingAction, threadId, block)
}
@OptIn(ExperimentalContracts::class)
suspend fun <T> TelegramBot.withUploadPhotoAction(chatId: IdChatIdentifier, block: TelegramBotActionCallback<T>) : T {
suspend fun <T> TelegramBot.withUploadPhotoAction(chatId: IdChatIdentifier, threadId: MessageThreadId? = chatId.threadId,block: TelegramBotActionCallback<T>) : T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return withAction(chatId, UploadPhotoAction, block)
return withAction(chatId, UploadPhotoAction, threadId, block)
}
@OptIn(ExperimentalContracts::class)
suspend fun <T> TelegramBot.withRecordVideoAction(chatId: IdChatIdentifier, block: TelegramBotActionCallback<T>) : T {
suspend fun <T> TelegramBot.withRecordVideoAction(chatId: IdChatIdentifier, threadId: MessageThreadId? = chatId.threadId,block: TelegramBotActionCallback<T>) : T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return withAction(chatId, RecordVideoAction, block)
return withAction(chatId, RecordVideoAction, threadId, block)
}
@OptIn(ExperimentalContracts::class)
suspend fun <T> TelegramBot.withUploadVideoAction(chatId: IdChatIdentifier, block: TelegramBotActionCallback<T>) : T {
suspend fun <T> TelegramBot.withUploadVideoAction(chatId: IdChatIdentifier, threadId: MessageThreadId? = chatId.threadId,block: TelegramBotActionCallback<T>) : T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return withAction(chatId, UploadVideoAction, block)
return withAction(chatId, UploadVideoAction, threadId, block)
}
@OptIn(ExperimentalContracts::class)
suspend fun <T> TelegramBot.withRecordVoiceAction(chatId: IdChatIdentifier, block: TelegramBotActionCallback<T>) : T {
suspend fun <T> TelegramBot.withRecordVoiceAction(chatId: IdChatIdentifier, threadId: MessageThreadId? = chatId.threadId,block: TelegramBotActionCallback<T>) : T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return withAction(chatId, RecordVoiceAction, block)
return withAction(chatId, RecordVoiceAction, threadId, block)
}
@OptIn(ExperimentalContracts::class)
suspend fun <T> TelegramBot.withUploadVoiceAction(chatId: IdChatIdentifier, block: TelegramBotActionCallback<T>) : T {
suspend fun <T> TelegramBot.withUploadVoiceAction(chatId: IdChatIdentifier, threadId: MessageThreadId? = chatId.threadId,block: TelegramBotActionCallback<T>) : T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return withAction(chatId, UploadVoiceAction, block)
return withAction(chatId, UploadVoiceAction, threadId, block)
}
@OptIn(ExperimentalContracts::class)
suspend fun <T> TelegramBot.withUploadDocumentAction(chatId: IdChatIdentifier, block: TelegramBotActionCallback<T>) : T {
suspend fun <T> TelegramBot.withUploadDocumentAction(chatId: IdChatIdentifier, threadId: MessageThreadId? = chatId.threadId,block: TelegramBotActionCallback<T>) : T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return withAction(chatId, UploadDocumentAction, block)
return withAction(chatId, UploadDocumentAction, threadId, block)
}
@OptIn(ExperimentalContracts::class)
suspend fun <T> TelegramBot.withFindLocationAction(chatId: IdChatIdentifier, block: TelegramBotActionCallback<T>) : T {
suspend fun <T> TelegramBot.withFindLocationAction(chatId: IdChatIdentifier, threadId: MessageThreadId? = chatId.threadId,block: TelegramBotActionCallback<T>) : T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return withAction(chatId, FindLocationAction, block)
return withAction(chatId, FindLocationAction, threadId, block)
}
@OptIn(ExperimentalContracts::class)
suspend fun <T> TelegramBot.withRecordVideoNoteAction(chatId: IdChatIdentifier, block: TelegramBotActionCallback<T>) : T {
suspend fun <T> TelegramBot.withRecordVideoNoteAction(chatId: IdChatIdentifier, threadId: MessageThreadId? = chatId.threadId,block: TelegramBotActionCallback<T>) : T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return withAction(chatId, RecordVideoNoteAction, block)
return withAction(chatId, RecordVideoNoteAction, threadId, block)
}
@OptIn(ExperimentalContracts::class)
suspend fun <T> TelegramBot.withUploadVideoNoteAction(chatId: IdChatIdentifier, block: TelegramBotActionCallback<T>) : T {
suspend fun <T> TelegramBot.withUploadVideoNoteAction(chatId: IdChatIdentifier, threadId: MessageThreadId? = chatId.threadId,block: TelegramBotActionCallback<T>) : T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return withAction(chatId, UploadVideoNoteAction, block)
return withAction(chatId, UploadVideoNoteAction, threadId, block)
}
@OptIn(ExperimentalContracts::class)
suspend fun <T> TelegramBot.withChooseStickerAction(chatId: IdChatIdentifier, block: TelegramBotActionCallback<T>) : T {
suspend fun <T> TelegramBot.withChooseStickerAction(chatId: IdChatIdentifier, threadId: MessageThreadId? = chatId.threadId,block: TelegramBotActionCallback<T>) : T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return withAction(chatId, ChooseStickerAction, block)
return withAction(chatId, ChooseStickerAction, threadId, block)
}
@OptIn(ExperimentalContracts::class)
suspend fun <T> TelegramBot.withTypingAction(chat: Chat, block: TelegramBotActionCallback<T>) : T {
suspend fun <T> TelegramBot.withTypingAction(chat: Chat, threadId: MessageThreadId? = chat.id.threadId,block: TelegramBotActionCallback<T>) : T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return withAction(chat, TypingAction, block)
return withAction(chat, TypingAction, threadId, block)
}
@OptIn(ExperimentalContracts::class)
suspend fun <T> TelegramBot.withUploadPhotoAction(chat: Chat, block: TelegramBotActionCallback<T>) : T {
suspend fun <T> TelegramBot.withUploadPhotoAction(chat: Chat, threadId: MessageThreadId? = chat.id.threadId,block: TelegramBotActionCallback<T>) : T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return withAction(chat, UploadPhotoAction, block)
return withAction(chat, UploadPhotoAction, threadId, block)
}
@OptIn(ExperimentalContracts::class)
suspend fun <T> TelegramBot.withRecordVideoAction(chat: Chat, block: TelegramBotActionCallback<T>) : T {
suspend fun <T> TelegramBot.withRecordVideoAction(chat: Chat, threadId: MessageThreadId? = chat.id.threadId,block: TelegramBotActionCallback<T>) : T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return withAction(chat, RecordVideoAction, block)
return withAction(chat, RecordVideoAction, threadId, block)
}
@OptIn(ExperimentalContracts::class)
suspend fun <T> TelegramBot.withUploadVideoAction(chat: Chat, block: TelegramBotActionCallback<T>) : T {
suspend fun <T> TelegramBot.withUploadVideoAction(chat: Chat, threadId: MessageThreadId? = chat.id.threadId,block: TelegramBotActionCallback<T>) : T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return withAction(chat, UploadVideoAction, block)
return withAction(chat, UploadVideoAction, threadId, block)
}
@OptIn(ExperimentalContracts::class)
suspend fun <T> TelegramBot.withRecordVoiceAction(chat: Chat, block: TelegramBotActionCallback<T>) : T {
suspend fun <T> TelegramBot.withRecordVoiceAction(chat: Chat, threadId: MessageThreadId? = chat.id.threadId,block: TelegramBotActionCallback<T>) : T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return withAction(chat, RecordVoiceAction, block)
return withAction(chat, RecordVoiceAction, threadId, block)
}
@OptIn(ExperimentalContracts::class)
suspend fun <T> TelegramBot.withUploadVoiceAction(chat: Chat, block: TelegramBotActionCallback<T>) : T {
suspend fun <T> TelegramBot.withUploadVoiceAction(chat: Chat, threadId: MessageThreadId? = chat.id.threadId,block: TelegramBotActionCallback<T>) : T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return withAction(chat, UploadVoiceAction, block)
return withAction(chat, UploadVoiceAction, threadId, block)
}
@OptIn(ExperimentalContracts::class)
suspend fun <T> TelegramBot.withUploadDocumentAction(chat: Chat, block: TelegramBotActionCallback<T>) : T {
suspend fun <T> TelegramBot.withUploadDocumentAction(chat: Chat, threadId: MessageThreadId? = chat.id.threadId,block: TelegramBotActionCallback<T>) : T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return withAction(chat, UploadDocumentAction, block)
return withAction(chat, UploadDocumentAction, threadId, block)
}
@OptIn(ExperimentalContracts::class)
suspend fun <T> TelegramBot.withFindLocationAction(chat: Chat, block: TelegramBotActionCallback<T>) : T {
suspend fun <T> TelegramBot.withFindLocationAction(chat: Chat, threadId: MessageThreadId? = chat.id.threadId,block: TelegramBotActionCallback<T>) : T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return withAction(chat, FindLocationAction, block)
return withAction(chat, FindLocationAction, threadId, block)
}
@OptIn(ExperimentalContracts::class)
suspend fun <T> TelegramBot.withRecordVideoNoteAction(chat: Chat, block: TelegramBotActionCallback<T>) : T {
suspend fun <T> TelegramBot.withRecordVideoNoteAction(chat: Chat, threadId: MessageThreadId? = chat.id.threadId,block: TelegramBotActionCallback<T>) : T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return withAction(chat, RecordVideoNoteAction, block)
return withAction(chat, RecordVideoNoteAction, threadId, block)
}
@OptIn(ExperimentalContracts::class)
suspend fun <T> TelegramBot.withUploadVideoNoteAction(chat: Chat, block: TelegramBotActionCallback<T>) : T {
suspend fun <T> TelegramBot.withUploadVideoNoteAction(chat: Chat, threadId: MessageThreadId? = chat.id.threadId,block: TelegramBotActionCallback<T>) : T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return withAction(chat, UploadVideoNoteAction, block)
return withAction(chat, UploadVideoNoteAction, threadId, block)
}
@OptIn(ExperimentalContracts::class)
suspend fun <T> TelegramBot.withChooseStickerAction(chat: Chat, block: TelegramBotActionCallback<T>) : T {
suspend fun <T> TelegramBot.withChooseStickerAction(chat: Chat, threadId: MessageThreadId? = chat.id.threadId,block: TelegramBotActionCallback<T>) : T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return withAction(chat, ChooseStickerAction, block)
return withAction(chat, ChooseStickerAction, threadId, block)
}

View File

@@ -56,6 +56,7 @@ suspend fun TelegramBot.send(
animation: AnimationFile,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -65,7 +66,7 @@ suspend fun TelegramBot.send(
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendAnimation(chatId, animation, text, parseMode, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendAnimation(chatId, animation, text, parseMode, spoilered, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* Will execute [sendAnimation] request
@@ -77,6 +78,7 @@ suspend fun TelegramBot.send(
animation: AnimationFile,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -86,7 +88,7 @@ suspend fun TelegramBot.send(
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendAnimation(chat, animation, text, parseMode, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendAnimation(chat, animation, text, parseMode, spoilered, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* Will execute [sendAnimation] request
@@ -97,6 +99,7 @@ suspend fun TelegramBot.send(
chatId: ChatIdentifier,
animation: AnimationFile,
entities: TextSourcesList,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -106,7 +109,7 @@ suspend fun TelegramBot.send(
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendAnimation(chatId, animation, entities, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendAnimation(chatId, animation, entities, spoilered, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* Will execute [sendAnimation] request
@@ -117,6 +120,7 @@ suspend fun TelegramBot.send(
chat: Chat,
animation: AnimationFile,
entities: TextSourcesList,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -126,7 +130,7 @@ suspend fun TelegramBot.send(
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendAnimation(chat, animation, entities, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendAnimation(chat, animation, entities, spoilered, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* Will execute [sendAudio] request
@@ -688,13 +692,14 @@ suspend fun TelegramBot.send(
photo: Photo,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
threadId: MessageThreadId? = chatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(chatId, photo, text, parseMode, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(chatId, photo, text, parseMode, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* Will execute [sendPhoto] request
@@ -706,13 +711,14 @@ suspend fun TelegramBot.send(
photo: Photo,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
threadId: MessageThreadId? = chat.id.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(chat, photo, text, parseMode, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(chat, photo, text, parseMode, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* Will execute [sendPhoto] request
@@ -724,13 +730,14 @@ suspend fun TelegramBot.send(
photoSize: PhotoSize,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
threadId: MessageThreadId? = chatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(chatId, photoSize, text, parseMode, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(chatId, photoSize, text, parseMode, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* Will execute [sendPhoto] request
@@ -742,13 +749,14 @@ suspend fun TelegramBot.send(
photoSize: PhotoSize,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
threadId: MessageThreadId? = chat.id.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(chat, photoSize, text, parseMode, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(chat, photoSize, text, parseMode, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* Will execute [sendPhoto] request
@@ -759,13 +767,14 @@ suspend inline fun TelegramBot.send(
chatId: ChatIdentifier,
photo: Photo,
entities: TextSourcesList,
spoilered: Boolean = false,
threadId: MessageThreadId? = chatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(chatId, photo, entities, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(chatId, photo, entities, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* Will execute [sendPhoto] request
@@ -776,13 +785,14 @@ suspend inline fun TelegramBot.send(
chat: Chat,
photo: Photo,
entities: TextSourcesList,
spoilered: Boolean = false,
threadId: MessageThreadId? = chat.id.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(chat, photo, entities, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(chat, photo, entities, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* Will execute [sendPhoto] request
@@ -793,13 +803,14 @@ suspend inline fun TelegramBot.send(
chatId: ChatIdentifier,
photoSize: PhotoSize,
entities: TextSourcesList,
spoilered: Boolean = false,
threadId: MessageThreadId? = chatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(chatId, photoSize, entities, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(chatId, photoSize, entities, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* Will execute [sendPhoto] request
@@ -810,13 +821,14 @@ suspend inline fun TelegramBot.send(
chat: Chat,
photoSize: PhotoSize,
entities: TextSourcesList,
spoilered: Boolean = false,
threadId: MessageThreadId? = chat.id.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(chat, photoSize, entities, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(chat, photoSize, entities, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* Will execute [sendRegularPoll] request
@@ -1357,13 +1369,14 @@ suspend fun TelegramBot.send(
video: VideoFile,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
threadId: MessageThreadId? = chatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendVideo(chatId, video, text, parseMode, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendVideo(chatId, video, text, parseMode, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* Will execute [sendVideo] request
@@ -1375,13 +1388,14 @@ suspend fun TelegramBot.send(
video: VideoFile,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
threadId: MessageThreadId? = chat.id.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendVideo(chat, video, text, parseMode, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendVideo(chat, video, text, parseMode, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* Will execute [sendVideo] request
@@ -1392,13 +1406,14 @@ suspend inline fun TelegramBot.send(
chatId: ChatIdentifier,
video: VideoFile,
entities: TextSourcesList,
spoilered: Boolean = false,
threadId: MessageThreadId? = chatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendVideo(chatId, video, entities, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendVideo(chatId, video, entities, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* Will execute [sendVideo] request
@@ -1409,13 +1424,14 @@ suspend inline fun TelegramBot.send(
chat: Chat,
video: VideoFile,
entities: TextSourcesList,
spoilered: Boolean = false,
threadId: MessageThreadId? = chat.id.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendVideo(chat, video, entities, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendVideo(chat, video, entities, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* Will execute [sendVideoNote] request

View File

@@ -23,6 +23,7 @@ suspend fun TelegramBot.sendAnimation(
thumb: InputFile? = null,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -39,6 +40,7 @@ suspend fun TelegramBot.sendAnimation(
thumb,
text,
parseMode,
spoilered,
duration,
width,
height,
@@ -60,6 +62,7 @@ suspend fun TelegramBot.sendAnimation(
animation: AnimationFile,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -70,7 +73,7 @@ suspend fun TelegramBot.sendAnimation(
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendAnimation(
chatId, animation.fileId, animation.thumb ?.fileId, text, parseMode, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup
chatId, animation.fileId, animation.thumb ?.fileId, text, parseMode, spoilered, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup
)
/**
@@ -83,6 +86,7 @@ suspend fun TelegramBot.sendAnimation(
thumb: InputFile? = null,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -92,7 +96,7 @@ suspend fun TelegramBot.sendAnimation(
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendAnimation(chat.id, animation, thumb, text, parseMode, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendAnimation(chat.id, animation, thumb, text, parseMode, spoilered, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or
@@ -103,6 +107,7 @@ suspend fun TelegramBot.sendAnimation(
animation: AnimationFile,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -112,7 +117,7 @@ suspend fun TelegramBot.sendAnimation(
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendAnimation(chat.id, animation, text, parseMode, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendAnimation(chat.id, animation, text, parseMode, spoilered, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
@@ -124,6 +129,7 @@ suspend fun TelegramBot.sendAnimation(
animation: InputFile,
thumb: InputFile? = null,
entities: TextSourcesList,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -139,6 +145,7 @@ suspend fun TelegramBot.sendAnimation(
animation,
thumb,
entities,
spoilered,
duration,
width,
height,
@@ -159,6 +166,7 @@ suspend fun TelegramBot.sendAnimation(
chatId: ChatIdentifier,
animation: AnimationFile,
entities: TextSourcesList,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -169,7 +177,7 @@ suspend fun TelegramBot.sendAnimation(
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendAnimation(
chatId, animation.fileId, animation.thumb ?.fileId, entities, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup
chatId, animation.fileId, animation.thumb ?.fileId, entities, spoilered, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup
)
/**
@@ -181,6 +189,7 @@ suspend fun TelegramBot.sendAnimation(
animation: InputFile,
thumb: InputFile? = null,
entities: TextSourcesList,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -190,7 +199,7 @@ suspend fun TelegramBot.sendAnimation(
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendAnimation(chat.id, animation, thumb, entities, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendAnimation(chat.id, animation, thumb, entities, spoilered, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or
@@ -200,6 +209,7 @@ suspend fun TelegramBot.sendAnimation(
chat: Chat,
animation: AnimationFile,
entities: TextSourcesList,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -209,4 +219,4 @@ suspend fun TelegramBot.sendAnimation(
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendAnimation(chat.id, animation, entities, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendAnimation(chat.id, animation, entities, spoilered, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)

View File

@@ -22,6 +22,7 @@ suspend fun TelegramBot.sendPhoto(
fileId: InputFile,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
threadId: MessageThreadId? = chatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
@@ -34,6 +35,7 @@ suspend fun TelegramBot.sendPhoto(
fileId,
text,
parseMode,
spoilered,
threadId,
disableNotification,
protectContent,
@@ -52,13 +54,14 @@ suspend fun TelegramBot.sendPhoto(
fileId: InputFile,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
threadId: MessageThreadId? = chat.id.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(chat.id, fileId, text, parseMode, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(chat.id, fileId, text, parseMode, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or
@@ -69,13 +72,14 @@ suspend fun TelegramBot.sendPhoto(
photo: Photo,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
threadId: MessageThreadId? = chatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(chatId, photo.biggest() ?.fileId ?: error("Photo content must not be empty"), text, parseMode, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(chatId, photo.biggest() ?.fileId ?: error("Photo content must not be empty"), text, parseMode, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or
@@ -86,13 +90,14 @@ suspend fun TelegramBot.sendPhoto(
photo: Photo,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
threadId: MessageThreadId? = chat.id.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(chat.id, photo, text, parseMode, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(chat.id, photo, text, parseMode, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or
@@ -103,13 +108,14 @@ suspend fun TelegramBot.sendPhoto(
photoSize: PhotoSize,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
threadId: MessageThreadId? = chatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(chatId, photoSize.fileId, text, parseMode, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(chatId, photoSize.fileId, text, parseMode, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or
@@ -120,13 +126,14 @@ suspend fun TelegramBot.sendPhoto(
photoSize: PhotoSize,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
threadId: MessageThreadId? = chat.id.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(chat.id, photoSize, text, parseMode, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(chat.id, photoSize, text, parseMode, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
@@ -137,6 +144,7 @@ suspend inline fun TelegramBot.sendPhoto(
chatId: ChatIdentifier,
fileId: InputFile,
entities: TextSourcesList,
spoilered: Boolean = false,
threadId: MessageThreadId? = chatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
@@ -148,6 +156,7 @@ suspend inline fun TelegramBot.sendPhoto(
chatId,
fileId,
entities,
spoilered,
threadId,
disableNotification,
protectContent,
@@ -165,13 +174,14 @@ suspend inline fun TelegramBot.sendPhoto(
chat: Chat,
fileId: InputFile,
entities: TextSourcesList,
spoilered: Boolean = false,
threadId: MessageThreadId? = chat.id.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(chat.id, fileId, entities, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(chat.id, fileId, entities, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or
@@ -181,13 +191,14 @@ suspend inline fun TelegramBot.sendPhoto(
chatId: ChatIdentifier,
photo: Photo,
entities: TextSourcesList,
spoilered: Boolean = false,
threadId: MessageThreadId? = chatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(chatId, photo.biggest() ?.fileId ?: error("Photo content must not be empty"), entities, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(chatId, photo.biggest() ?.fileId ?: error("Photo content must not be empty"), entities, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or
@@ -197,13 +208,14 @@ suspend inline fun TelegramBot.sendPhoto(
chat: Chat,
photo: Photo,
entities: TextSourcesList,
spoilered: Boolean = false,
threadId: MessageThreadId? = chat.id.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(chat.id, photo, entities, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(chat.id, photo, entities, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or
@@ -213,13 +225,14 @@ suspend inline fun TelegramBot.sendPhoto(
chatId: ChatIdentifier,
photoSize: PhotoSize,
entities: TextSourcesList,
spoilered: Boolean = false,
threadId: MessageThreadId? = chatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(chatId, photoSize.fileId, entities, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(chatId, photoSize.fileId, entities, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or
@@ -229,10 +242,11 @@ suspend inline fun TelegramBot.sendPhoto(
chat: Chat,
photoSize: PhotoSize,
entities: TextSourcesList,
spoilered: Boolean = false,
threadId: MessageThreadId? = chat.id.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendPhoto(chat.id, photoSize, entities, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendPhoto(chat.id, photoSize, entities, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)

View File

@@ -23,6 +23,7 @@ suspend fun TelegramBot.sendVideo(
thumb: InputFile? = null,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -39,6 +40,7 @@ suspend fun TelegramBot.sendVideo(
thumb,
text,
parseMode,
spoilered,
duration,
width,
height,
@@ -61,13 +63,14 @@ suspend fun TelegramBot.sendVideo(
video: VideoFile,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
threadId: MessageThreadId? = chatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendVideo(chatId, video.fileId, video.thumb ?.fileId, text, parseMode, video.duration, video.width, video.height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendVideo(chatId, video.fileId, video.thumb ?.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
@@ -79,6 +82,7 @@ suspend fun TelegramBot.sendVideo(
thumb: InputFile? = null,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -88,7 +92,7 @@ suspend fun TelegramBot.sendVideo(
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendVideo(chat.id, video, thumb, text, parseMode, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendVideo(chat.id, video, thumb, text, parseMode, spoilered, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
@@ -100,13 +104,14 @@ suspend fun TelegramBot.sendVideo(
video: VideoFile,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
threadId: MessageThreadId? = chat.id.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendVideo(chat.id, video, text, parseMode, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendVideo(chat.id, video, text, parseMode, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
* @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or
@@ -117,6 +122,7 @@ suspend inline fun TelegramBot.sendVideo(
video: InputFile,
thumb: InputFile? = null,
entities: TextSourcesList,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -132,6 +138,7 @@ suspend inline fun TelegramBot.sendVideo(
video,
thumb,
entities,
spoilered,
duration,
width,
height,
@@ -153,13 +160,14 @@ suspend inline fun TelegramBot.sendVideo(
chatId: ChatIdentifier,
video: VideoFile,
entities: TextSourcesList,
spoilered: Boolean = false,
threadId: MessageThreadId? = chatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendVideo(chatId, video.fileId, video.thumb ?.fileId, entities, video.duration, video.width, video.height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendVideo(chatId, video.fileId, video.thumb ?.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
@@ -170,6 +178,7 @@ suspend inline fun TelegramBot.sendVideo(
video: InputFile,
thumb: InputFile? = null,
entities: TextSourcesList,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -179,7 +188,7 @@ suspend inline fun TelegramBot.sendVideo(
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendVideo(chat.id, video, thumb, entities, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendVideo(chat.id, video, thumb, entities, spoilered, duration, width, height, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/**
@@ -190,10 +199,11 @@ suspend inline fun TelegramBot.sendVideo(
chat: Chat,
video: VideoFile,
entities: TextSourcesList,
spoilered: Boolean = false,
threadId: MessageThreadId? = chat.id.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendVideo(chat.id, video, entities, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) = sendVideo(chat.id, video, entities, spoilered, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)

View File

@@ -10,6 +10,8 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers_registrar.T
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlin.reflect.KClass
/**
@@ -133,6 +135,9 @@ class DefaultBehaviourContextWithFSM<T : State>(
private val additionalHandlers = mutableListOf<BehaviourWithFSMStateHandlerHolder<*, T>>()
private var actualHandlersList = additionalHandlers + handlers
protected val statesJobs = mutableMapOf<T, Job>()
protected val statesJobsMutex = Mutex()
override suspend fun launchStateHandling(state: T, handlers: List<CheckableHandlerHolder<in T, T>>): T? {
return launchStateHandling(state, handlers, onStateHandlingErrorHandler)
}
@@ -164,21 +169,49 @@ class DefaultBehaviourContextWithFSM<T : State>(
statesManager.endChain(state)
}
}
fun Job.enableRemoveOnCompletion(state: T) {
invokeOnCompletion {
launchSafelyWithoutExceptions {
statesJobsMutex.withLock {
if (this@enableRemoveOnCompletion === statesJobs[state]) {
statesJobs.remove(state)
}
}
}
}
}
statesManager.onStartChain.subscribeSafelyWithoutExceptions(this) {
launch { statePerformer(it) }
statesJobsMutex.withLock {
runCatchingSafely { statesJobs.remove(it) ?.cancel() }
statesJobs[it] = launch { statePerformer(it) }.apply { enableRemoveOnCompletion(it) }
}
}
statesManager.onEndChain.subscribeSafelyWithoutExceptions(this) {
statesJobsMutex.withLock {
runCatchingSafely { statesJobs.remove(it) ?.cancel() }
}
updatesFlows.remove(it.context)
}
statesManager.onChainStateUpdated.subscribeSafelyWithoutExceptions(this) { (old, new) ->
statesJobsMutex.withLock {
runCatchingSafely { statesJobs.remove(old) ?.cancel() }
runCatchingSafely { statesJobs.remove(new) ?.cancel() }
statesJobs[new] = launch { statePerformer(new) }.apply { enableRemoveOnCompletion(new) }
}
if (old.context != new.context) {
updatesFlows.remove(old.context)
}
launch { statePerformer(new) }
}
statesManager.onEndChain.subscribeSafelyWithoutExceptions(this) {
updatesFlows.remove(it.context)
}
statesManager.getActiveStates().forEach {
launch { statePerformer(it) }
statesJobsMutex.withLock {
runCatchingSafely { statesJobs.remove(it) ?.cancel() }
statesJobs[it] = launch { statePerformer(it) }.apply { enableRemoveOnCompletion(it) }
}
}
}
/**

View File

@@ -9,7 +9,11 @@ import dev.inmo.tgbotapi.types.message.ChatEvents.*
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.*
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicClosed
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicCreated
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicEdited
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicReopened
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.GeneralForumTopicHidden
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.GeneralForumTopicUnhidden
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.WriteAccessAllowed
import dev.inmo.tgbotapi.types.message.ChatEvents.voice.*
import dev.inmo.tgbotapi.types.message.abstracts.ChatEventMessage
import dev.inmo.tgbotapi.types.message.payments.SuccessfulPaymentEvent
@@ -151,3 +155,19 @@ suspend fun BehaviourContext.waitForumTopicReopened(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEvents<ForumTopicReopened>(initRequest, errorFactory)
suspend fun BehaviourContext.waitForumTopicEdited(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEvents<ForumTopicEdited>(initRequest, errorFactory)
suspend fun BehaviourContext.waitGeneralForumTopicHidden(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEvents<GeneralForumTopicHidden>(initRequest, errorFactory)
suspend fun BehaviourContext.waitGeneralForumTopicUnhidden(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEvents<GeneralForumTopicUnhidden>(initRequest, errorFactory)
suspend fun BehaviourContext.waitWriteAccessAllowed(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEvents<WriteAccessAllowed>(initRequest, errorFactory)

View File

@@ -13,7 +13,11 @@ import dev.inmo.tgbotapi.types.message.ChatEvents.*
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.*
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicClosed
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicCreated
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicEdited
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicReopened
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.GeneralForumTopicHidden
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.GeneralForumTopicUnhidden
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.WriteAccessAllowed
import dev.inmo.tgbotapi.types.message.ChatEvents.voice.*
import dev.inmo.tgbotapi.types.message.PrivateEventMessage
import dev.inmo.tgbotapi.types.message.abstracts.ChatEventMessage
@@ -575,3 +579,81 @@ suspend fun <BC : BehaviourContext> BC.onForumTopicReopened(
markerFactory: MarkerFactory<in ChatEventMessage<ForumTopicReopened>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, SupergroupEventMessage<ForumTopicReopened>>
) = onEventWithCustomChatEventMessage(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param markerFactory Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun <BC : BehaviourContext> BC.onForumTopicEdited(
initialFilter: SimpleFilter<SupergroupEventMessage<ForumTopicEdited>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, SupergroupEventMessage<ForumTopicEdited>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<ForumTopicEdited>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, SupergroupEventMessage<ForumTopicEdited>>
) = onEventWithCustomChatEventMessage(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param markerFactory Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun <BC : BehaviourContext> BC.onGeneralForumTopicHidden(
initialFilter: SimpleFilter<SupergroupEventMessage<GeneralForumTopicHidden>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, SupergroupEventMessage<GeneralForumTopicHidden>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<GeneralForumTopicHidden>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, SupergroupEventMessage<GeneralForumTopicHidden>>
) = onEventWithCustomChatEventMessage(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param markerFactory Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun <BC : BehaviourContext> BC.onGeneralForumTopicUnhidden(
initialFilter: SimpleFilter<SupergroupEventMessage<GeneralForumTopicUnhidden>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, SupergroupEventMessage<GeneralForumTopicUnhidden>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<GeneralForumTopicUnhidden>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, SupergroupEventMessage<GeneralForumTopicUnhidden>>
) = onEventWithCustomChatEventMessage(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param markerFactory Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun <BC : BehaviourContext> BC.onWriteAccessAllowed(
initialFilter: SimpleFilter<SupergroupEventMessage<WriteAccessAllowed>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, SupergroupEventMessage<WriteAccessAllowed>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<WriteAccessAllowed>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, SupergroupEventMessage<WriteAccessAllowed>>
) = onEventWithCustomChatEventMessage(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)

View File

@@ -0,0 +1,5 @@
package dev.inmo.tgbotapi.abstracts
interface SpoilerableData {
val spoilered: Boolean
}

View File

@@ -30,7 +30,7 @@ class KtorRequestsExecutor(
client: HttpClient = HttpClient(),
callsFactories: List<KtorCallFactory> = emptyList(),
excludeDefaultFactories: Boolean = false,
private val requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter(),
private val requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter,
private val jsonFormatter: Json = nonstrictJsonFormat,
private val pipelineStepsHolder: KtorPipelineStepsHolder = KtorPipelineStepsHolder
) : BaseRequestsExecutor(telegramAPIUrlsKeeper) {
@@ -51,7 +51,7 @@ class KtorRequestsExecutor(
override suspend fun <T : Any> execute(request: Request<T>): T {
return runCatchingSafely {
pipelineStepsHolder.onBeforeSearchCallFactory(request, callsFactories)
requestsLimiter.limit {
requestsLimiter.limit(request) {
var result: T? = null
lateinit var factoryHandledRequest: KtorCallFactory
for (potentialFactory in callsFactories) {
@@ -111,7 +111,7 @@ class KtorRequestsExecutorBuilder(
var client: HttpClient = HttpClient()
var callsFactories: List<KtorCallFactory> = emptyList()
var excludeDefaultFactories: Boolean = false
var requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter()
var requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter
var jsonFormatter: Json = nonstrictJsonFormat
fun build() = KtorRequestsExecutor(telegramAPIUrlsKeeper, client, callsFactories, excludeDefaultFactories, requestsLimiter, jsonFormatter)

View File

@@ -1,66 +1,18 @@
package dev.inmo.tgbotapi.bot.settings.limiters
import dev.inmo.micro_utils.coroutines.safely
import dev.inmo.tgbotapi.bot.exceptions.TooMuchRequestsException
import dev.inmo.tgbotapi.types.MilliSeconds
import dev.inmo.tgbotapi.types.RetryAfterError
import io.ktor.client.plugins.ClientRequestException
import io.ktor.http.HttpStatusCode
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.first
/**
* This limiter will limit requests only after getting a [RetryAfterError] or [ClientRequestException] with
* [HttpStatusCode.TooManyRequests] status code. Important thing is that in case if some of block has been blocked, all
* the others will wait until it will be possible to be called
*
* @param defaultTooManyRequestsDelay This parameter will be used in case of getting [ClientRequestException] with
* [HttpStatusCode.TooManyRequests] as a parameter for delay like it would be [TooMuchRequestsException]. The reason of
* it is that in [ClientRequestException] there is no information about required delay between requests
* Simple limiter which will lock any request when [TooMuchRequestsExceptions] is thrown and rerun request after lock time
*/
class ExceptionsOnlyLimiter(
private val defaultTooManyRequestsDelay: MilliSeconds = 1000L
) : RequestLimiter {
private val lockState = MutableStateFlow(false)
private suspend fun lock(timeMillis: MilliSeconds) {
try {
safely {
lockState.emit(true)
delay(timeMillis)
}
} finally {
lockState.emit(false)
}
}
object ExceptionsOnlyLimiter : RequestLimiter {
override suspend fun <T> limit(block: suspend () -> T): T {
while (true) {
lockState.first { !it }
var throwable: Throwable? = null
val result = safely({
throwable = when (it) {
is TooMuchRequestsException -> {
lock(it.retryAfter.leftToRetry)
it
}
is ClientRequestException -> {
if (it.response.status == HttpStatusCode.TooManyRequests) {
lock(defaultTooManyRequestsDelay)
} else {
throw it
}
it
}
else -> throw it
}
null
}) {
block()
}
if (throwable == null) {
return result!!
}
return try {
block()
} catch (e: TooMuchRequestsException) {
delay(e.retryAfter.leftToRetry)
limit(block)
}
}
}

View File

@@ -0,0 +1,5 @@
package dev.inmo.tgbotapi.bot.settings.limiters
object NoLimitsLimiter : RequestLimiter {
override suspend fun <T> limit(block: suspend () -> T): T = block()
}

View File

@@ -1,8 +1,12 @@
package dev.inmo.tgbotapi.bot.settings.limiters
import dev.inmo.tgbotapi.requests.abstracts.Request
interface RequestLimiter {
/**
* Use limit for working of block (like delay between or after, for example)
*/
suspend fun <T> limit(block: suspend () -> T): T
suspend fun <T : Any> limit(request: Request<T>, block: suspend () -> T) = limit(block)
}

View File

@@ -0,0 +1,18 @@
package dev.inmo.tgbotapi.requests.chat.forum
import dev.inmo.tgbotapi.abstracts.types.ChatRequest
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.utils.RGBColor
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
@Serializable
data class CloseGeneralForumTopic (
@SerialName(chatIdField)
override val chatId: ChatIdentifier
): ModifyForumRequest, GeneralForumRequest<Boolean> {
override fun method(): String = "closeGeneralForumTopic"
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -1,11 +1,7 @@
package dev.inmo.tgbotapi.requests.chat.forum
import dev.inmo.tgbotapi.abstracts.types.ChatRequest
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.utils.RGBColor
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
@Serializable
data class EditForumTopic (
@@ -14,12 +10,12 @@ data class EditForumTopic (
@SerialName(messageThreadIdField)
val messageThreadId: MessageThreadId,
@SerialName(nameField)
val name: String,
val name: String? = null,
@SerialName(iconCustomEmojiIdField)
val iconEmojiId: CustomEmojiId,
val iconEmojiId: CustomEmojiId? = null,
): ModifyForumRequest {
init {
if (name.length !in threadNameLength) {
if (name != null && name.length !in threadNameLength) {
throw IllegalArgumentException("Thread name must be in $threadNameLength range")
}
}

View File

@@ -0,0 +1,22 @@
package dev.inmo.tgbotapi.requests.chat.forum
import dev.inmo.tgbotapi.types.*
import kotlinx.serialization.*
@Serializable
data class EditGeneralForumTopic (
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
@SerialName(nameField)
val name: String
): ModifyForumRequest, GeneralForumRequest<Boolean> {
init {
if (name.length !in threadNameLength) {
throw IllegalArgumentException("Thread name must be in $threadNameLength range")
}
}
override fun method(): String = "editGeneralForumTopic"
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -0,0 +1,6 @@
package dev.inmo.tgbotapi.requests.chat.forum
import dev.inmo.tgbotapi.abstracts.types.ChatRequest
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
sealed interface GeneralForumRequest<T : Any> : ForumRequest<T>, ChatRequest

View File

@@ -0,0 +1,18 @@
package dev.inmo.tgbotapi.requests.chat.forum
import dev.inmo.tgbotapi.abstracts.types.ChatRequest
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.utils.RGBColor
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
@Serializable
data class HideGeneralForumTopic (
@SerialName(chatIdField)
override val chatId: ChatIdentifier
): ModifyForumRequest, GeneralForumRequest<Boolean> {
override fun method(): String = "hideGeneralForumTopic"
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -0,0 +1,18 @@
package dev.inmo.tgbotapi.requests.chat.forum
import dev.inmo.tgbotapi.abstracts.types.ChatRequest
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.utils.RGBColor
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
@Serializable
data class ReopenGeneralForumTopic (
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
): ModifyForumRequest, GeneralForumRequest<Boolean> {
override fun method(): String = "reopenGeneralForumTopic"
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -0,0 +1,18 @@
package dev.inmo.tgbotapi.requests.chat.forum
import dev.inmo.tgbotapi.abstracts.types.ChatRequest
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.utils.RGBColor
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
@Serializable
data class UnhideGeneralForumTopic (
@SerialName(chatIdField)
override val chatId: ChatIdentifier
): ModifyForumRequest, GeneralForumRequest<Boolean> {
override fun method(): String = "unhideGeneralForumTopic"
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -18,7 +18,7 @@ data class SetChatAdministratorCustomTitle(
override val resultDeserializer: DeserializationStrategy<Boolean>
get() = Boolean.serializer()
override val requestSerializer: SerializationStrategy<*>
get() = RestrictChatMember.serializer()
get() = serializer()
init {
if (customTitle.length !in customTitleLength) {

View File

@@ -1,5 +1,6 @@
package dev.inmo.tgbotapi.requests.send
import dev.inmo.tgbotapi.requests.send.abstracts.OptionallyMessageThreadRequest
import dev.inmo.tgbotapi.requests.send.abstracts.SendChatMessageRequest
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.actions.BotAction
@@ -14,8 +15,10 @@ data class SendAction(
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
@SerialName(actionField)
val action: BotAction
): SendChatMessageRequest<Boolean> {
val action: BotAction,
@SerialName(messageThreadIdField)
override val threadId: MessageThreadId? = chatId.threadId
): SendChatMessageRequest<Boolean>, OptionallyMessageThreadRequest {
override fun method(): String = "sendChatAction"
override val resultDeserializer: DeserializationStrategy<Boolean>
get() = Boolean.serializer()

View File

@@ -0,0 +1,5 @@
package dev.inmo.tgbotapi.requests.send.abstracts
import dev.inmo.tgbotapi.abstracts.SpoilerableData
interface OptionallyWithSpoilerRequest : SpoilerableData

View File

@@ -25,6 +25,7 @@ fun SendAnimation(
thumb: InputFile? = null,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -47,6 +48,7 @@ fun SendAnimation(
text,
parseMode,
null,
spoilered,
duration,
width,
height,
@@ -73,6 +75,7 @@ fun SendAnimation(
animation: InputFile,
thumb: InputFile? = null,
entities: TextSourcesList,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -95,6 +98,7 @@ fun SendAnimation(
entities.makeString(),
null,
entities.toRawMessageEntities(),
spoilered,
duration,
width,
height,
@@ -133,6 +137,8 @@ data class SendAnimationData internal constructor(
override val parseMode: ParseMode? = null,
@SerialName(captionEntitiesField)
private val rawEntities: List<RawMessageEntity>? = null,
@SerialName(hasSpoilerField)
override val spoilered: Boolean = false,
@SerialName(durationField)
override val duration: Long? = null,
@SerialName(widthField)
@@ -157,7 +163,8 @@ data class SendAnimationData internal constructor(
TextableSendMessageRequest<ContentMessage<AnimationContent>>,
ThumbedSendMessageRequest<ContentMessage<AnimationContent>>,
DuratedSendMessageRequest<ContentMessage<AnimationContent>>,
SizedSendMessageRequest<ContentMessage<AnimationContent>>
SizedSendMessageRequest<ContentMessage<AnimationContent>>,
OptionallyWithSpoilerRequest
{
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text ?: return@lazy null)

View File

@@ -37,7 +37,7 @@ fun <T : MediaGroupPartContent> SendMediaGroup(
protectContent: Boolean = false,
replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null
): Request<PossiblySentViaBotCommonMessage<T>> {
): Request<PossiblySentViaBotCommonMessage<MediaGroupContent<T>>> {
if (media.size !in mediaCountInMediaGroup) {
throwRangeError("Count of members in media group", mediaCountInMediaGroup, media.size)
}
@@ -70,7 +70,7 @@ fun <T : MediaGroupPartContent> SendMediaGroup(
data,
SendMediaGroupFiles(files)
)
}) as Request<PossiblySentViaBotCommonMessage<T>>
}) as Request<PossiblySentViaBotCommonMessage<MediaGroupContent<T>>>
}
/**

View File

@@ -23,6 +23,7 @@ fun SendPhoto(
photo: InputFile,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
threadId: MessageThreadId? = chatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
@@ -36,6 +37,7 @@ fun SendPhoto(
text,
parseMode,
null,
spoilered,
threadId,
disableNotification,
protectContent,
@@ -55,6 +57,7 @@ fun SendPhoto(
chatId: ChatIdentifier,
photo: InputFile,
entities: TextSourcesList,
spoilered: Boolean = false,
threadId: MessageThreadId? = chatId.threadId,
disableNotification: Boolean = false,
protectContent: Boolean = false,
@@ -68,6 +71,7 @@ fun SendPhoto(
entities.makeString(),
null,
entities.toRawMessageEntities(),
spoilered,
threadId,
disableNotification,
protectContent,
@@ -98,6 +102,8 @@ data class SendPhotoData internal constructor(
override val parseMode: ParseMode? = null,
@SerialName(captionEntitiesField)
private val rawEntities: List<RawMessageEntity>? = null,
@SerialName(hasSpoilerField)
override val spoilered: Boolean = false,
@SerialName(messageThreadIdField)
override val threadId: MessageThreadId? = chatId.threadId,
@SerialName(disableNotificationField)
@@ -113,7 +119,8 @@ data class SendPhotoData internal constructor(
) : DataRequest<ContentMessage<PhotoContent>>,
SendMessageRequest<ContentMessage<PhotoContent>>,
ReplyingMarkupSendMessageRequest<ContentMessage<PhotoContent>>,
TextableSendMessageRequest<ContentMessage<PhotoContent>>
TextableSendMessageRequest<ContentMessage<PhotoContent>>,
OptionallyWithSpoilerRequest
{
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text ?: return@lazy null)

View File

@@ -25,6 +25,7 @@ fun SendVideo(
thumb: InputFile? = null,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -48,6 +49,7 @@ fun SendVideo(
text,
parseMode,
null,
spoilered,
duration,
width,
height,
@@ -75,6 +77,7 @@ fun SendVideo(
video: InputFile,
thumb: InputFile? = null,
entities: TextSourcesList,
spoilered: Boolean = false,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
@@ -98,6 +101,7 @@ fun SendVideo(
entities.makeString(),
null,
entities.toRawMessageEntities(),
spoilered,
duration,
width,
height,
@@ -137,6 +141,8 @@ data class SendVideoData internal constructor(
override val parseMode: ParseMode? = null,
@SerialName(captionEntitiesField)
private val rawEntities: List<RawMessageEntity>? = null,
@SerialName(hasSpoilerField)
override val spoilered: Boolean = false,
@SerialName(durationField)
override val duration: Long? = null,
@SerialName(widthField)
@@ -163,7 +169,8 @@ data class SendVideoData internal constructor(
TextableSendMessageRequest<ContentMessage<VideoContent>>,
ThumbedSendMessageRequest<ContentMessage<VideoContent>>,
DuratedSendMessageRequest<ContentMessage<VideoContent>>,
SizedSendMessageRequest<ContentMessage<VideoContent>>
SizedSendMessageRequest<ContentMessage<VideoContent>>,
OptionallyWithSpoilerRequest
{
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text ?: return@lazy null)

View File

@@ -54,6 +54,13 @@ value class ChatIdWithThreadId(val chatIdWithThreadId: Pair<Identifier, MessageT
val ChatIdentifier.threadId: MessageThreadId?
get() = (this as? IdChatIdentifier) ?.threadId
fun IdChatIdentifier.toChatId() = when (this) {
is ChatId -> this
is ChatIdWithThreadId -> ChatId(chatId)
}
fun IdChatIdentifier.toChatWithThreadId(threadId: MessageThreadId) = IdChatIdentifier(chatId, threadId)
/**
* https://core.telegram.org/bots/api#formatting-options
*/

View File

@@ -228,6 +228,7 @@ const val allowsMultipleAnswersField = "allows_multiple_answers"
const val isAnonymousField = "is_anonymous"
const val canManageTopicsField = "can_manage_topics"
const val captionEntitiesField = "caption_entities"
const val hasSpoilerField = "has_spoiler"
const val loginUrlField = "login_url"
const val forwardTextField = "forward_text"
const val botUsernameField = "bot_username"
@@ -242,8 +243,10 @@ const val customTitleField = "custom_title"
const val optionIdsField = "option_ids"
const val ipAddressField = "ip_address"
const val linkedChatIdField = "linked_chat_id"
const val hasHiddenMembersField = "has_hidden_members"
const val joinToSendMessagesField = "join_to_send_messages"
const val joinByRequestField = "join_by_request"
const val hasAggressiveAntiSpamEnabledField = "has_aggressive_anti_spam_enabled"
const val horizontalAccuracyField = "horizontal_accuracy"
const val revokeMessagesField = "revoke_messages"
const val messageAutoDeleteTimeField = "message_auto_delete_time"
@@ -461,6 +464,7 @@ const val shouldSendEmailToProviderField = "send_email_to_provider"
const val resizeKeyboardField = "resize_keyboard"
const val oneTimeKeyboardField = "one_time_keyboard"
const val inputFieldPlaceholderField = "input_field_placeholder"
const val isPersistentField = "is_persistent"
const val priceDependOnShipAddressField = "is_flexible"

View File

@@ -13,7 +13,9 @@ data class ReplyKeyboardMarkup(
val oneTimeKeyboard: Boolean? = null,
@SerialName(inputFieldPlaceholderField)
val inputFieldPlaceholder: String? = null,
val selective: Boolean? = null
val selective: Boolean? = null,
@SerialName(isPersistentField)
val persistent: Boolean? = null
) : KeyboardMarkup {
init {
if (inputFieldPlaceholder != null && inputFieldPlaceholder.length !in inputFieldPlaceholderLimit) {

View File

@@ -27,7 +27,9 @@ data class ExtendedChannelChatImpl(
@Serializable(TelegramBotAPIMessageDeserializeOnlySerializer::class)
override val pinnedMessage: Message? = null,
@SerialName(linkedChatIdField)
override val linkedGroupChatId: IdChatIdentifier? = null
override val linkedGroupChatId: IdChatIdentifier? = null,
@SerialName(hasHiddenMembersField)
override val membersHidden: Boolean = false
) : ExtendedChannelChat
@Serializable
@@ -46,7 +48,9 @@ data class ExtendedGroupChatImpl(
override val inviteLink: String? = null,
@SerialName(pinnedMessageField)
@Serializable(TelegramBotAPIMessageDeserializeOnlySerializer::class)
override val pinnedMessage: Message? = null
override val pinnedMessage: Message? = null,
@SerialName(hasHiddenMembersField)
override val membersHidden: Boolean = false
) : ExtendedGroupChat
@Serializable
@@ -109,7 +113,11 @@ data class ExtendedSupergroupChatImpl(
@SerialName(joinToSendMessagesField)
override val requiresJoinForMessaging: Boolean = false,
@SerialName(joinByRequestField)
override val requireAdminApproveToJoin: Boolean = false
override val requireAdminApproveToJoin: Boolean = false,
@SerialName(hasAggressiveAntiSpamEnabledField)
override val isAggressiveAntiSpamEnabled: Boolean = false,
@SerialName(hasHiddenMembersField)
override val membersHidden: Boolean = false
) : ExtendedSupergroupChat
@Serializable
@@ -146,7 +154,11 @@ data class ExtendedForumChatImpl(
@SerialName(joinToSendMessagesField)
override val requiresJoinForMessaging: Boolean = false,
@SerialName(joinByRequestField)
override val requireAdminApproveToJoin: Boolean = false
override val requireAdminApproveToJoin: Boolean = false,
@SerialName(hasAggressiveAntiSpamEnabledField)
override val isAggressiveAntiSpamEnabled: Boolean = false,
@SerialName(hasHiddenMembersField)
override val membersHidden: Boolean = false
) : ExtendedForumChat
@Serializable

View File

@@ -31,6 +31,7 @@ sealed interface ExtendedPublicChat : ExtendedChat, PublicChat {
val inviteLink: String?
@Serializable(TelegramBotAPIMessageDeserializeOnlySerializer::class)
val pinnedMessage: Message?
val membersHidden: Boolean
}
@Serializable(ExtendedChatSerializer::class)
@@ -50,6 +51,11 @@ sealed interface ExtendedSupergroupChat : SupergroupChat, ExtendedGroupChat, Ext
* This field represents field "join_by_request" from API
*/
val requireAdminApproveToJoin: Boolean
/**
* This field represents field "has_aggressive_anti_spam_enabled" from API
*/
val isAggressiveAntiSpamEnabled: Boolean
}
@Serializable(ExtendedChatSerializer::class)

View File

@@ -34,11 +34,13 @@ data class VideoFile(
@Suppress("NOTHING_TO_INLINE")
inline fun VideoFile.toTelegramMediaVideo(
text: String? = null,
parseMode: ParseMode? = null
parseMode: ParseMode? = null,
spoilered: Boolean = false
) = TelegramMediaVideo(
fileId,
text,
parseMode,
spoilered,
width,
height,
duration,
@@ -47,10 +49,12 @@ inline fun VideoFile.toTelegramMediaVideo(
@Suppress("NOTHING_TO_INLINE")
inline fun VideoFile.toTelegramMediaVideo(
textSources: TextSourcesList
textSources: TextSourcesList,
spoilered: Boolean = false
) = TelegramMediaVideo(
fileId,
textSources,
spoilered,
width,
height,
duration,

View File

@@ -20,4 +20,4 @@ sealed interface AudioMediaGroupMemberTelegramMedia: MediaGroupMemberTelegramMed
sealed interface DocumentMediaGroupMemberTelegramMedia: MediaGroupMemberTelegramMedia
@Serializable(MediaGroupMemberTelegramMediaSerializer::class)
sealed interface VisualMediaGroupMemberTelegramMedia : MediaGroupMemberTelegramMedia
sealed interface VisualMediaGroupMemberTelegramMedia : MediaGroupMemberTelegramMedia, SpoilerableTelegramMedia

View File

@@ -0,0 +1,5 @@
package dev.inmo.tgbotapi.types.media
import dev.inmo.tgbotapi.abstracts.SpoilerableData
sealed interface SpoilerableTelegramMedia : TelegramMedia, SpoilerableData

View File

@@ -18,15 +18,17 @@ fun TelegramMediaAnimation(
file: InputFile,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
width: Int? = null,
height: Int? = null,
duration: Long? = null,
thumb: InputFile? = null
) = TelegramMediaAnimation(file, text, parseMode, null, width, height, duration, thumb)
) = TelegramMediaAnimation(file, text, parseMode, null, spoilered, width, height, duration, thumb)
fun TelegramMediaAnimation(
file: InputFile,
entities: TextSourcesList,
spoilered: Boolean = false,
width: Int? = null,
height: Int? = null,
duration: Long? = null,
@@ -36,6 +38,7 @@ fun TelegramMediaAnimation(
entities.makeString(),
null,
entities.toRawMessageEntities(),
spoilered,
width,
height,
duration,
@@ -51,11 +54,13 @@ data class TelegramMediaAnimation internal constructor(
override val parseMode: ParseMode? = null,
@SerialName(captionEntitiesField)
private val rawEntities: List<RawMessageEntity>? = null,
@SerialName(hasSpoilerField)
override val spoilered: Boolean = false,
override val width: Int? = null,
override val height: Int? = null,
override val duration: Long? = null,
override val thumb: InputFile? = null
) : TelegramMedia, SizedTelegramMedia, DuratedTelegramMedia, ThumbedTelegramMedia, TextedOutput {
) : TelegramMedia, SizedTelegramMedia, DuratedTelegramMedia, ThumbedTelegramMedia, TextedOutput, SpoilerableTelegramMedia {
override val type: String = "animation"
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text ?: return@lazy null)

View File

@@ -18,13 +18,15 @@ internal const val photoTelegramMediaType = "photo"
fun TelegramMediaPhoto(
file: InputFile,
text: String? = null,
parseMode: ParseMode? = null
) = TelegramMediaPhoto(file, text, parseMode, null)
parseMode: ParseMode? = null,
spoilered: Boolean = false
) = TelegramMediaPhoto(file, text, parseMode, null, spoilered)
fun TelegramMediaPhoto(
file: InputFile,
entities: TextSourcesList
) = TelegramMediaPhoto(file, entities.makeString(), null, entities.toRawMessageEntities())
entities: TextSourcesList,
spoilered: Boolean = false
) = TelegramMediaPhoto(file, entities.makeString(), null, entities.toRawMessageEntities(), spoilered)
@Serializable
data class TelegramMediaPhoto internal constructor(
@@ -34,7 +36,9 @@ data class TelegramMediaPhoto internal constructor(
@SerialName(parseModeField)
override val parseMode: ParseMode? = null,
@SerialName(captionEntitiesField)
private val rawEntities: List<RawMessageEntity>? = null
private val rawEntities: List<RawMessageEntity>? = null,
@SerialName(hasSpoilerField)
override val spoilered: Boolean = false,
) : TelegramMedia, VisualMediaGroupMemberTelegramMedia {
override val type: String = photoTelegramMediaType
override val textSources: TextSourcesList? by lazy {
@@ -50,16 +54,20 @@ data class TelegramMediaPhoto internal constructor(
fun PhotoSize.toTelegramMediaPhoto(
text: String? = null,
parseMode: ParseMode? = null
parseMode: ParseMode? = null,
spoilered: Boolean = false
): TelegramMediaPhoto = TelegramMediaPhoto(
fileId,
text,
parseMode
parseMode,
spoilered
)
fun PhotoSize.toTelegramMediaPhoto(
textSources: TextSourcesList = emptyList()
textSources: TextSourcesList = emptyList(),
spoilered: Boolean = false
): TelegramMediaPhoto = TelegramMediaPhoto(
fileId,
textSources
textSources,
spoilered
)

View File

@@ -18,20 +18,22 @@ fun TelegramMediaVideo(
file: InputFile,
text: String? = null,
parseMode: ParseMode? = null,
spoilered: Boolean = false,
width: Int? = null,
height: Int? = null,
duration: Long? = null,
thumb: InputFile? = null
) = TelegramMediaVideo(file, text, parseMode, null, width, height, duration, thumb)
) = TelegramMediaVideo(file, text, parseMode, null, spoilered, width, height, duration, thumb)
fun TelegramMediaVideo(
file: InputFile,
entities: TextSourcesList,
spoilered: Boolean = false,
width: Int? = null,
height: Int? = null,
duration: Long? = null,
thumb: InputFile? = null
) = TelegramMediaVideo(file, entities.makeString(), null, entities.toRawMessageEntities(), width, height, duration, thumb)
) = TelegramMediaVideo(file, entities.makeString(), null, entities.toRawMessageEntities(), spoilered, width, height, duration, thumb)
@Serializable
data class TelegramMediaVideo internal constructor (
@@ -42,6 +44,8 @@ data class TelegramMediaVideo internal constructor (
override val parseMode: ParseMode? = null,
@SerialName(captionEntitiesField)
private val rawEntities: List<RawMessageEntity>? = null,
@SerialName(hasSpoilerField)
override val spoilered: Boolean = false,
override val width: Int? = null,
override val height: Int? = null,
override val duration: Long? = null,

View File

@@ -0,0 +1,18 @@
package dev.inmo.tgbotapi.types.message.ChatEvents.forum
import dev.inmo.tgbotapi.types.CustomEmojiId
import dev.inmo.tgbotapi.types.iconColorField
import dev.inmo.tgbotapi.types.iconCustomEmojiIdField
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.ForumEvent
import dev.inmo.tgbotapi.types.nameField
import dev.inmo.tgbotapi.utils.RGBColor
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class ForumTopicEdited(
@SerialName(nameField)
val name: String,
@SerialName(iconCustomEmojiIdField)
val iconEmojiId: CustomEmojiId? = null
) : ForumEvent

View File

@@ -0,0 +1,7 @@
package dev.inmo.tgbotapi.types.message.ChatEvents.forum
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.ForumEvent
import kotlinx.serialization.Serializable
@Serializable
object GeneralForumTopicHidden : ForumEvent

View File

@@ -0,0 +1,7 @@
package dev.inmo.tgbotapi.types.message.ChatEvents.forum
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.ForumEvent
import kotlinx.serialization.Serializable
@Serializable
object GeneralForumTopicUnhidden : ForumEvent

View File

@@ -0,0 +1,7 @@
package dev.inmo.tgbotapi.types.message.ChatEvents.forum
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.ForumEvent
import kotlinx.serialization.Serializable
@Serializable
object WriteAccessAllowed : ForumEvent

View File

@@ -14,7 +14,11 @@ import dev.inmo.tgbotapi.types.message.ChatEvents.*
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.*
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicClosed
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicCreated
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicEdited
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicReopened
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.GeneralForumTopicHidden
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.GeneralForumTopicUnhidden
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.WriteAccessAllowed
import dev.inmo.tgbotapi.types.message.ChatEvents.voice.*
import dev.inmo.tgbotapi.types.message.abstracts.*
import dev.inmo.tgbotapi.types.message.content.*
@@ -58,6 +62,7 @@ internal data class RawMessage(
private val entities: RawMessageEntities? = null,
private val caption: String? = null,
private val caption_entities: RawMessageEntities? = null,
private val has_media_spoiler: Boolean? = null,
private val audio: AudioFile? = null,
private val document: DocumentFile? = null,
private val animation: AnimationFile? = null,
@@ -96,8 +101,12 @@ internal data class RawMessage(
// Forum
private val forum_topic_created: ForumTopicCreated? = null,
private val forum_topic_edited: ForumTopicEdited? = null,
private val forum_topic_closed: ForumTopicClosed? = null,
private val forum_topic_reopened: ForumTopicReopened? = null,
private val general_forum_topic_hidden: GeneralForumTopicHidden? = null,
private val general_forum_topic_unhidden: GeneralForumTopicUnhidden? = null,
private val write_access_allowed: WriteAccessAllowed? = null,
// AutoDelete Message time changed
private val message_auto_delete_timer_changed: MessageAutoDeleteTimerChanged? = null,
@@ -129,13 +138,15 @@ internal data class RawMessage(
video != null -> VideoContent(
video,
caption,
adaptedCaptionEntities
adaptedCaptionEntities,
has_media_spoiler ?: false
)
animation != null -> AnimationContent(
animation,
document,
caption,
adaptedCaptionEntities
adaptedCaptionEntities,
has_media_spoiler ?: false
)
document != null -> DocumentContent(
document,
@@ -150,7 +161,8 @@ internal data class RawMessage(
photo != null -> PhotoContent(
photo.toList(),
caption,
adaptedCaptionEntities
adaptedCaptionEntities,
has_media_spoiler ?: false
)
sticker != null -> StickerContent(sticker)
dice != null -> DiceContent(dice)
@@ -213,6 +225,10 @@ internal data class RawMessage(
video_chat_scheduled != null -> video_chat_scheduled
message_auto_delete_timer_changed != null -> message_auto_delete_timer_changed
forum_topic_created != null -> forum_topic_created
forum_topic_edited != null -> forum_topic_edited
general_forum_topic_hidden != null -> general_forum_topic_hidden
general_forum_topic_unhidden != null -> general_forum_topic_unhidden
write_access_allowed != null -> write_access_allowed
forum_topic_closed != null -> forum_topic_closed
forum_topic_reopened != null -> forum_topic_reopened
video_chat_ended != null -> video_chat_ended

View File

@@ -1,5 +1,6 @@
package dev.inmo.tgbotapi.types.message.content
import dev.inmo.tgbotapi.abstracts.SpoilerableData
import dev.inmo.tgbotapi.utils.internal.ClassCastsIncluded
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.types.ChatIdentifier
@@ -23,6 +24,7 @@ sealed interface MessageContent: ResendableContent {
mediaGroupPartContentAdditionalBuilder: PolymorphicModuleBuilder<MediaGroupPartContent>.() -> Unit = {},
textedMediaContentAdditionalBuilder: PolymorphicModuleBuilder<TextedMediaContent>.() -> Unit = {},
mediaContentAdditionalBuilder: PolymorphicModuleBuilder<MediaContent>.() -> Unit = {},
spoilerableMediaContentAdditionalBuilder: PolymorphicModuleBuilder<SpoilerableMediaContent>.() -> Unit = {},
mediaCollectionContentAdditionalBuilder: PolymorphicModuleBuilder<MediaCollectionContent<*>>.() -> Unit = {},
additionalBuilder: PolymorphicModuleBuilder<MessageContent>.() -> Unit = {}
) = SerializersModule {
@@ -66,6 +68,13 @@ sealed interface MessageContent: ResendableContent {
mediaContentAdditionalBuilder()
}
polymorphic(SpoilerableMediaContent::class) {
subclass(VideoContent::class)
subclass(PhotoContent::class)
subclass(AnimationContent::class)
spoilerableMediaContentAdditionalBuilder()
}
polymorphic(TextedMediaContent::class) {
subclass(PhotoContent::class)
subclass(VoiceContent::class)
@@ -111,6 +120,8 @@ sealed interface MediaContent: MessageContent {
fun asTelegramMedia(): TelegramMedia
}
sealed interface SpoilerableMediaContent : MediaContent, SpoilerableData
@ClassCastsIncluded
sealed interface ResendableContent {
fun createResend(

View File

@@ -39,6 +39,6 @@ sealed interface MediaGroupPartContent : TextedMediaContent {
fun toMediaGroupMemberTelegramMedia(): MediaGroupMemberTelegramMedia
}
sealed interface VisualMediaGroupPartContent : MediaGroupPartContent {
sealed interface VisualMediaGroupPartContent : MediaGroupPartContent, SpoilerableMediaContent {
override fun toMediaGroupMemberTelegramMedia(): VisualMediaGroupMemberTelegramMedia
}

View File

@@ -18,8 +18,9 @@ data class AnimationContent(
override val media: AnimationFile,
val includedDocument: DocumentFile?,
override val text: String?,
override val textSources: TextSourcesList = emptyList()
) : TextedMediaContent {
override val textSources: TextSourcesList = emptyList(),
override val spoilered: Boolean = false
) : TextedMediaContent, SpoilerableMediaContent {
override fun createResend(
chatId: ChatIdentifier,
messageThreadId: MessageThreadId?,
@@ -33,6 +34,7 @@ data class AnimationContent(
media.fileId,
media.thumb ?.fileId,
textSources,
spoilered,
media.duration,
media.width,
media.height,
@@ -47,6 +49,7 @@ data class AnimationContent(
override fun asTelegramMedia(): TelegramMediaAnimation = TelegramMediaAnimation(
media.fileId,
textSources,
spoilered,
media.width,
media.height,
media.duration,

View File

@@ -17,7 +17,8 @@ import kotlinx.serialization.Serializable
data class PhotoContent(
override val mediaCollection: Photo,
override val text: String? = null,
override val textSources: TextSourcesList = emptyList()
override val textSources: TextSourcesList = emptyList(),
override val spoilered: Boolean = false
) : MediaCollectionContent<PhotoSize>, VisualMediaGroupPartContent {
override val media: PhotoSize = mediaCollection.biggest() ?: throw IllegalStateException("Can't locate any photo size for this content")
@@ -33,6 +34,7 @@ data class PhotoContent(
chatId,
media.fileId,
textSources,
spoilered,
messageThreadId,
disableNotification,
protectContent,
@@ -43,5 +45,5 @@ data class PhotoContent(
override fun toMediaGroupMemberTelegramMedia(): TelegramMediaPhoto = asTelegramMedia()
override fun asTelegramMedia(): TelegramMediaPhoto = media.toTelegramMediaPhoto(textSources)
override fun asTelegramMedia(): TelegramMediaPhoto = media.toTelegramMediaPhoto(textSources, spoilered)
}

View File

@@ -17,7 +17,8 @@ import kotlinx.serialization.Serializable
data class VideoContent(
override val media: VideoFile,
override val text: String? = null,
override val textSources: TextSourcesList = emptyList()
override val textSources: TextSourcesList = emptyList(),
override val spoilered: Boolean = false
) : VisualMediaGroupPartContent {
override fun createResend(
chatId: ChatIdentifier,
@@ -32,6 +33,7 @@ data class VideoContent(
media.fileId,
media.thumb ?.fileId,
textSources,
spoilered,
media.duration,
media.width,
media.height,

View File

@@ -213,6 +213,7 @@ import dev.inmo.tgbotapi.types.media.DocumentMediaGroupMemberTelegramMedia
import dev.inmo.tgbotapi.types.media.DuratedTelegramMedia
import dev.inmo.tgbotapi.types.media.MediaGroupMemberTelegramMedia
import dev.inmo.tgbotapi.types.media.SizedTelegramMedia
import dev.inmo.tgbotapi.types.media.SpoilerableTelegramMedia
import dev.inmo.tgbotapi.types.media.TelegramMedia
import dev.inmo.tgbotapi.types.media.TelegramMediaAnimation
import dev.inmo.tgbotapi.types.media.TelegramMediaAudio
@@ -251,7 +252,11 @@ import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.SupergroupEvent
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.VideoChatEvent
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicClosed
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicCreated
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicEdited
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicReopened
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.GeneralForumTopicHidden
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.GeneralForumTopicUnhidden
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.WriteAccessAllowed
import dev.inmo.tgbotapi.types.message.ChatEvents.voice.VideoChatEnded
import dev.inmo.tgbotapi.types.message.ChatEvents.voice.VideoChatParticipantsInvited
import dev.inmo.tgbotapi.types.message.ChatEvents.voice.VideoChatScheduled
@@ -315,6 +320,7 @@ import dev.inmo.tgbotapi.types.message.content.MessageContent
import dev.inmo.tgbotapi.types.message.content.PhotoContent
import dev.inmo.tgbotapi.types.message.content.PollContent
import dev.inmo.tgbotapi.types.message.content.ResendableContent
import dev.inmo.tgbotapi.types.message.content.SpoilerableMediaContent
import dev.inmo.tgbotapi.types.message.content.StaticLocationContent
import dev.inmo.tgbotapi.types.message.content.StickerContent
import dev.inmo.tgbotapi.types.message.content.TextContent
@@ -2643,6 +2649,16 @@ public inline fun TelegramMedia.sizedTelegramMediaOrThrow(): SizedTelegramMedia
public inline fun <T> TelegramMedia.ifSizedTelegramMedia(block: (SizedTelegramMedia) -> T): T? =
sizedTelegramMediaOrNull() ?.let(block)
public inline fun TelegramMedia.spoilerableTelegramMediaOrNull(): SpoilerableTelegramMedia? = this
as? dev.inmo.tgbotapi.types.media.SpoilerableTelegramMedia
public inline fun TelegramMedia.spoilerableTelegramMediaOrThrow(): SpoilerableTelegramMedia = this
as dev.inmo.tgbotapi.types.media.SpoilerableTelegramMedia
public inline fun <T>
TelegramMedia.ifSpoilerableTelegramMedia(block: (SpoilerableTelegramMedia) -> T): T? =
spoilerableTelegramMediaOrNull() ?.let(block)
public inline fun TelegramMedia.telegramMediaAnimationOrNull(): TelegramMediaAnimation? = this as?
dev.inmo.tgbotapi.types.media.TelegramMediaAnimation
@@ -2923,6 +2939,15 @@ public inline fun ChatEvent.forumTopicCreatedOrThrow(): ForumTopicCreated = this
public inline fun <T> ChatEvent.ifForumTopicCreated(block: (ForumTopicCreated) -> T): T? =
forumTopicCreatedOrNull() ?.let(block)
public inline fun ChatEvent.forumTopicEditedOrNull(): ForumTopicEdited? = this as?
dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicEdited
public inline fun ChatEvent.forumTopicEditedOrThrow(): ForumTopicEdited = this as
dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicEdited
public inline fun <T> ChatEvent.ifForumTopicEdited(block: (ForumTopicEdited) -> T): T? =
forumTopicEditedOrNull() ?.let(block)
public inline fun ChatEvent.forumTopicReopenedOrNull(): ForumTopicReopened? = this as?
dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicReopened
@@ -2932,6 +2957,34 @@ public inline fun ChatEvent.forumTopicReopenedOrThrow(): ForumTopicReopened = th
public inline fun <T> ChatEvent.ifForumTopicReopened(block: (ForumTopicReopened) -> T): T? =
forumTopicReopenedOrNull() ?.let(block)
public inline fun ChatEvent.generalForumTopicHiddenOrNull(): GeneralForumTopicHidden? = this as?
dev.inmo.tgbotapi.types.message.ChatEvents.forum.GeneralForumTopicHidden
public inline fun ChatEvent.generalForumTopicHiddenOrThrow(): GeneralForumTopicHidden = this as
dev.inmo.tgbotapi.types.message.ChatEvents.forum.GeneralForumTopicHidden
public inline fun <T> ChatEvent.ifGeneralForumTopicHidden(block: (GeneralForumTopicHidden) -> T): T?
= generalForumTopicHiddenOrNull() ?.let(block)
public inline fun ChatEvent.generalForumTopicUnhiddenOrNull(): GeneralForumTopicUnhidden? = this as?
dev.inmo.tgbotapi.types.message.ChatEvents.forum.GeneralForumTopicUnhidden
public inline fun ChatEvent.generalForumTopicUnhiddenOrThrow(): GeneralForumTopicUnhidden = this as
dev.inmo.tgbotapi.types.message.ChatEvents.forum.GeneralForumTopicUnhidden
public inline fun <T>
ChatEvent.ifGeneralForumTopicUnhidden(block: (GeneralForumTopicUnhidden) -> T): T? =
generalForumTopicUnhiddenOrNull() ?.let(block)
public inline fun ChatEvent.writeAccessAllowedOrNull(): WriteAccessAllowed? = this as?
dev.inmo.tgbotapi.types.message.ChatEvents.forum.WriteAccessAllowed
public inline fun ChatEvent.writeAccessAllowedOrThrow(): WriteAccessAllowed = this as
dev.inmo.tgbotapi.types.message.ChatEvents.forum.WriteAccessAllowed
public inline fun <T> ChatEvent.ifWriteAccessAllowed(block: (WriteAccessAllowed) -> T): T? =
writeAccessAllowedOrNull() ?.let(block)
public inline fun ChatEvent.videoChatEndedOrNull(): VideoChatEnded? = this as?
dev.inmo.tgbotapi.types.message.ChatEvents.voice.VideoChatEnded
@@ -3516,6 +3569,16 @@ public inline fun ResendableContent.mediaContentOrThrow(): MediaContent = this a
public inline fun <T> ResendableContent.ifMediaContent(block: (MediaContent) -> T): T? =
mediaContentOrNull() ?.let(block)
public inline fun ResendableContent.spoilerableMediaContentOrNull(): SpoilerableMediaContent? = this
as? dev.inmo.tgbotapi.types.message.content.SpoilerableMediaContent
public inline fun ResendableContent.spoilerableMediaContentOrThrow(): SpoilerableMediaContent = this
as dev.inmo.tgbotapi.types.message.content.SpoilerableMediaContent
public inline fun <T>
ResendableContent.ifSpoilerableMediaContent(block: (SpoilerableMediaContent) -> T): T? =
spoilerableMediaContentOrNull() ?.let(block)
public inline fun ResendableContent.audioMediaGroupPartContentOrNull(): AudioMediaGroupPartContent?
= this as? dev.inmo.tgbotapi.types.message.content.AudioMediaGroupPartContent

View File

@@ -22,7 +22,8 @@ fun ReplyKeyboardBuilder.build(
oneTimeKeyboard: Boolean? = null,
inputFieldPlaceholder: String? = null,
selective: Boolean? = null,
) = ReplyKeyboardMarkup(matrix, resizeKeyboard, oneTimeKeyboard, inputFieldPlaceholder, selective)
persistent: Boolean? = null,
) = ReplyKeyboardMarkup(matrix, resizeKeyboard, oneTimeKeyboard, inputFieldPlaceholder, selective, persistent)
/**
* Row builder of [KeyboardButton]
@@ -43,8 +44,9 @@ inline fun replyKeyboard(
oneTimeKeyboard: Boolean? = null,
inputFieldPlaceholder: String? = null,
selective: Boolean? = null,
persistent: Boolean? = null,
block: ReplyKeyboardBuilder.() -> Unit
) = ReplyKeyboardBuilder().apply(block).build(resizeKeyboard, oneTimeKeyboard, inputFieldPlaceholder, selective)
) = ReplyKeyboardBuilder().apply(block).build(resizeKeyboard, oneTimeKeyboard, inputFieldPlaceholder, selective, persistent)
/**
* Factory-function for [ReplyKeyboardBuilder], but in difference with [replyKeyboard] this method will create single-row
@@ -55,8 +57,9 @@ inline fun flatReplyKeyboard(
oneTimeKeyboard: Boolean? = null,
inputFieldPlaceholder: String? = null,
selective: Boolean? = null,
persistent: Boolean? = null,
block: ReplyKeyboardRowBuilder.() -> Unit
) = replyKeyboard(resizeKeyboard, oneTimeKeyboard, inputFieldPlaceholder, selective) {
) = replyKeyboard(resizeKeyboard, oneTimeKeyboard, inputFieldPlaceholder, selective, persistent) {
row<KeyboardButton>(block)
}

View File

@@ -9,11 +9,13 @@ fun ReplyKeyboardMarkup(
resizeKeyboard: Boolean? = null,
oneTimeKeyboard: Boolean? = null,
inputFieldPlaceholder: String? = null,
selective: Boolean? = null
selective: Boolean? = null,
persistent: Boolean? = null
): ReplyKeyboardMarkup = ReplyKeyboardMarkup(
flatMatrix { buttons.forEach { +it } },
resizeKeyboard,
oneTimeKeyboard,
inputFieldPlaceholder,
selective
selective,
persistent
)

View File

@@ -7,6 +7,7 @@ import dev.inmo.tgbotapi.bot.exceptions.*
import dev.inmo.tgbotapi.extensions.utils.updates.convertWithMediaGroupUpdates
import dev.inmo.tgbotapi.extensions.utils.updates.lastUpdateIdentifier
import dev.inmo.tgbotapi.requests.GetUpdates
import dev.inmo.tgbotapi.requests.webhook.DeleteWebhook
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage
import dev.inmo.tgbotapi.types.message.content.MediaGroupContent
@@ -23,7 +24,14 @@ fun TelegramBot.longPollingFlow(
timeoutSeconds: Seconds = 30,
exceptionsHandler: (ExceptionHandler<Unit>)? = null,
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
autoDisableWebhooks: Boolean = true
): Flow<Update> = channelFlow {
if (autoDisableWebhooks) {
runCatchingSafely {
execute(DeleteWebhook())
}
}
var lastUpdateIdentifier: UpdateIdentifier? = null
while (isActive) {
@@ -86,8 +94,9 @@ fun TelegramBot.startGettingOfUpdatesByLongPolling(
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
exceptionsHandler: (ExceptionHandler<Unit>)? = null,
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
autoDisableWebhooks: Boolean = true,
updatesReceiver: UpdateReceiver<Update>
): Job = longPollingFlow(timeoutSeconds, exceptionsHandler, allowedUpdates).subscribeSafely(
): Job = longPollingFlow(timeoutSeconds, exceptionsHandler, allowedUpdates, autoDisableWebhooks).subscribeSafely(
scope,
exceptionsHandler ?: defaultSafelyExceptionHandler,
updatesReceiver
@@ -101,7 +110,8 @@ fun TelegramBot.createAccumulatedUpdatesRetrieverFlow(
avoidInlineQueries: Boolean = false,
avoidCallbackQueries: Boolean = false,
exceptionsHandler: ExceptionHandler<Unit>? = null,
allowedUpdates: List<String>? = ALL_UPDATES_LIST
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
autoDisableWebhooks: Boolean = true,
): Flow<Update> = longPollingFlow(
timeoutSeconds = 0,
exceptionsHandler = {
@@ -111,7 +121,8 @@ fun TelegramBot.createAccumulatedUpdatesRetrieverFlow(
else -> exceptionsHandler ?.invoke(it)
}
},
allowedUpdates = allowedUpdates
allowedUpdates = allowedUpdates,
autoDisableWebhooks = autoDisableWebhooks
).filter {
!(it is InlineQueryUpdate && avoidInlineQueries || it is CallbackQueryUpdate && avoidCallbackQueries)
}
@@ -122,12 +133,14 @@ fun TelegramBot.retrieveAccumulatedUpdates(
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
exceptionsHandler: (ExceptionHandler<Unit>)? = null,
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
autoDisableWebhooks: Boolean = true,
updatesReceiver: UpdateReceiver<Update>
): Job = createAccumulatedUpdatesRetrieverFlow(
avoidInlineQueries,
avoidCallbackQueries,
exceptionsHandler,
allowedUpdates
allowedUpdates,
autoDisableWebhooks
).subscribeSafelyWithoutExceptions(
scope.LinkedSupervisorScope()
) {
@@ -139,6 +152,7 @@ fun TelegramBot.retrieveAccumulatedUpdates(
avoidInlineQueries: Boolean = false,
avoidCallbackQueries: Boolean = false,
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
autoDisableWebhooks: Boolean = true,
exceptionsHandler: ExceptionHandler<Unit>? = null
) = retrieveAccumulatedUpdates(
avoidInlineQueries,
@@ -146,6 +160,7 @@ fun TelegramBot.retrieveAccumulatedUpdates(
scope,
exceptionsHandler,
flowsUpdatesFilter.allowedUpdates,
autoDisableWebhooks,
flowsUpdatesFilter.asUpdateReceiver
)
@@ -155,6 +170,7 @@ suspend fun TelegramBot.flushAccumulatedUpdates(
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
exceptionsHandler: ExceptionHandler<Unit>? = null,
autoDisableWebhooks: Boolean = true,
updatesReceiver: UpdateReceiver<Update> = {}
) = retrieveAccumulatedUpdates(
avoidInlineQueries,
@@ -162,6 +178,7 @@ suspend fun TelegramBot.flushAccumulatedUpdates(
scope,
exceptionsHandler,
allowedUpdates,
autoDisableWebhooks,
updatesReceiver
).join()
@@ -173,9 +190,10 @@ fun TelegramBot.longPolling(
updatesFilter: UpdatesFilter,
timeoutSeconds: Seconds = 30,
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
autoDisableWebhooks: Boolean = true,
exceptionsHandler: ExceptionHandler<Unit>? = null
): Job = updatesFilter.run {
startGettingOfUpdatesByLongPolling(timeoutSeconds, scope, exceptionsHandler, allowedUpdates, asUpdateReceiver)
startGettingOfUpdatesByLongPolling(timeoutSeconds, scope, exceptionsHandler, allowedUpdates, autoDisableWebhooks, asUpdateReceiver)
}
/**
@@ -189,18 +207,21 @@ fun TelegramBot.longPolling(
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
exceptionsHandler: ExceptionHandler<Unit>? = null,
flowsUpdatesFilterUpdatesKeeperCount: Int = 100,
autoDisableWebhooks: Boolean = true,
flowUpdatesPreset: FlowsUpdatesFilter.() -> Unit
): Job = longPolling(FlowsUpdatesFilter(flowsUpdatesFilterUpdatesKeeperCount).apply(flowUpdatesPreset), timeoutSeconds, scope, exceptionsHandler)
): Job = longPolling(FlowsUpdatesFilter(flowsUpdatesFilterUpdatesKeeperCount).apply(flowUpdatesPreset), timeoutSeconds, scope, autoDisableWebhooks, exceptionsHandler)
fun RequestsExecutor.startGettingOfUpdatesByLongPolling(
updatesFilter: UpdatesFilter,
timeoutSeconds: Seconds = 30,
exceptionsHandler: ExceptionHandler<Unit>? = null,
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
autoDisableWebhooks: Boolean = true,
): Job = startGettingOfUpdatesByLongPolling(
timeoutSeconds,
scope,
exceptionsHandler,
updatesFilter.allowedUpdates,
autoDisableWebhooks,
updatesFilter.asUpdateReceiver
)

View File

@@ -1,5 +1,7 @@
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.tgbotapi.extensions.utils.updates.convertWithMediaGroupUpdates
import dev.inmo.tgbotapi.types.message.abstracts.PossiblyMediaGroupMessage
import dev.inmo.tgbotapi.types.update.abstracts.BaseMessageUpdate
@@ -29,15 +31,18 @@ fun CoroutineScope.updateHandlerWithMediaGroupsAdaptation(
)
launch {
launch {
launchSafelyWithoutExceptions {
for (update in updatesChannel) {
when (val data = update.data) {
is PossiblyMediaGroupMessage<*> -> mediaGroupChannel.send("${data.mediaGroupId}${update::class.simpleName}" to update as BaseMessageUpdate)
val data = update.data
when {
data is PossiblyMediaGroupMessage<*> && data.mediaGroupId != null -> {
mediaGroupChannel.send("${data.mediaGroupId}${update::class.simpleName}" to update as BaseMessageUpdate)
}
else -> output(update)
}
}
}
launch {
launchSafelyWithoutExceptions {
for ((_, mediaGroup) in mediaGroupAccumulatedChannel) {
mediaGroup.convertWithMediaGroupUpdates().forEach {
output(it)

View File

@@ -41,10 +41,9 @@ fun Route.includeWebhookHandlingInRoute(
post {
try {
runCatchingSafely {
val asJson = nonstrictJsonFormat.parseToJsonElement(call.receiveText())
val update = nonstrictJsonFormat.decodeFromJsonElement(
val update = nonstrictJsonFormat.decodeFromString(
UpdateDeserializationStrategy,
asJson
call.receiveText()
)
transformer(update)
}.onSuccess {

View File

@@ -6,3 +6,5 @@ typealias EventHandler = WebApp.() -> Unit
typealias ViewportChangedEventHandler = WebApp.(ViewportChangedData) -> Unit
typealias InvoiceClosedEventHandler = WebApp.(InvoiceClosedInfo) -> Unit
typealias PopupClosedEventHandler = WebApp.(String?) -> Unit
typealias QRTextReceivedEventHandler = WebApp.(String) -> Boolean
typealias TextReceivedEventHandler = WebApp.(String) -> Unit

View File

@@ -8,4 +8,6 @@ sealed class EventType(val typeName: String) {
object SettingsButtonClicked : EventType("settingsButtonClicked")
object InvoiceClosed : EventType("invoiceClosed")
object PopupClosed : EventType("popupClosed")
object QRTextReceived : EventType("qrTextReceived")
object ClipboardTextReceived : EventType("clipboardTextReceived")
}

View File

@@ -0,0 +1,16 @@
package dev.inmo.tgbotapi.webapps
import kotlin.js.json
external interface OpenLinkParams {
@JsName("try_instant_view")
val tryInstantView: Boolean
}
fun OpenLinkParams(
tryInstantView: Boolean
) = json(
*listOfNotNull(
"try_instant_view" to tryInstantView
).toTypedArray()
).unsafeCast<OpenLinkParams>()

View File

@@ -0,0 +1,3 @@
package dev.inmo.tgbotapi.webapps
typealias QRTextReceivedCallback = (String) -> Boolean

View File

@@ -0,0 +1,3 @@
package dev.inmo.tgbotapi.webapps
typealias TextReceivedCallback = (String) -> Unit

View File

@@ -8,6 +8,8 @@ import dev.inmo.tgbotapi.webapps.popup.*
external class WebApp {
val version: String
val platform: String
val initData: String
val initDataUnsafe: WebAppInitData
@@ -33,6 +35,9 @@ external class WebApp {
fun showPopup(params: PopupParams, callback: ClosePopupCallback? = definedExternally)
fun showAlert(message: String, callback: AlertCallback? = definedExternally)
fun showConfirm(message: String, callback: ConfirmCallback? = definedExternally)
fun showScanQrPopup(params: ScanQrPopupParams, callback: QRTextReceivedCallback? = definedExternally)
fun closeScanQrPopup()
fun readTextFromClipboard(callback: TextReceivedCallback? = definedExternally)
@JsName("MainButton")
val mainButton: MainButton
@@ -50,6 +55,10 @@ external class WebApp {
internal fun onEventWithInvoiceClosedInfo(type: String, callback: (InvoiceClosedInfo) -> Unit)
@JsName("onEvent")
internal fun onEventWithPopupClosedInfo(type: String, callback: (String?) -> Unit)
@JsName("onEvent")
internal fun onEventWithQRTextInfo(type: String, callback: (String) -> Boolean)
@JsName("onEvent")
internal fun onEventWithTextInfo(type: String, callback: (String) -> Unit)
fun offEvent(type: String, callback: () -> Unit)
@JsName("offEvent")
@@ -124,6 +133,30 @@ fun WebApp.onEvent(type: EventType.PopupClosed, eventHandler: PopupClosedEventHa
)
}
/**
* @return The callback which should be used in case you want to turn off events handling
*/
fun WebApp.onEvent(type: EventType.QRTextReceived, eventHandler: QRTextReceivedEventHandler) = { it: String ->
eventHandler(js("this").unsafeCast<WebApp>(), it)
}.also {
onEventWithQRTextInfo(
type.typeName,
callback = it
)
}
/**
* @return The callback which should be used in case you want to turn off events handling
*/
fun WebApp.onEvent(type: EventType.ClipboardTextReceived, eventHandler: TextReceivedEventHandler) = { it: String ->
eventHandler(js("this").unsafeCast<WebApp>(), it)
}.also {
onEventWithTextInfo(
type.typeName,
callback = it
)
}
/**
* @return The callback which should be used in case you want to turn off events handling
*/
@@ -152,6 +185,14 @@ fun WebApp.onInvoiceClosed(eventHandler: InvoiceClosedEventHandler) = onEvent(Ev
* @return The callback which should be used in case you want to turn off events handling
*/
fun WebApp.onPopupClosed(eventHandler: PopupClosedEventHandler) = onEvent(EventType.PopupClosed, eventHandler)
/**
* @return The callback which should be used in case you want to turn off events handling
*/
fun WebApp.onQRTextReceived(eventHandler: QRTextReceivedEventHandler) = onEvent(EventType.QRTextReceived, eventHandler)
/**
* @return The callback which should be used in case you want to turn off events handling
*/
fun WebApp.onClipboardTextReceived(eventHandler: TextReceivedEventHandler) = onEvent(EventType.ClipboardTextReceived, eventHandler)
fun WebApp.isInitDataSafe(botToken: String) = TelegramAPIUrlsKeeper(botToken).checkWebAppData(
initData,

View File

@@ -0,0 +1,16 @@
package dev.inmo.tgbotapi.webapps.popup
import kotlin.js.json
external interface ScanQrPopupParams {
val text: String?
}
fun ScanQrPopupParams(
text: String? = null
) = json(
*listOfNotNull(
("text" to text).takeIf { text != null }
).toTypedArray()
).unsafeCast<ScanQrPopupParams>()