mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2025-11-16 12:00:18 +00:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 421d5ae9e3 | |||
| 54f1181a14 | |||
| f616a02f7c | |||
| f1deb93147 | |||
| 2300b44aae | |||
| fe88cf037a | |||
| 89920abe35 | |||
| 4c4aa491cb | |||
| f0a4425be9 | |||
| 6c8af4cab3 | |||
| 017d57e5e5 | |||
| 5a456bcdbf | |||
| 4182d8f3fe | |||
| c6e2cba09b | |||
| 8dd3eefd15 | |||
| b72d4da8f0 | |||
| ebd023669d | |||
| f7be4e557e | |||
| ec434c6af4 | |||
| 0398590de6 | |||
| 9ef1b54ada | |||
| c30ce5c803 | |||
| c0a50bccb0 | |||
| e0cd7dc512 | |||
| 6ff621b428 | |||
| 964a61749c | |||
| 17930091ac | |||
| 2271beadfb | |||
| 44c48a8462 | |||
| 4d35f89ad1 | |||
| 174706b189 | |||
| fe17312bb5 | |||
| d8b5789cd2 | |||
| f27d0916db | |||
| 2d3fe45389 |
47
CHANGELOG.md
47
CHANGELOG.md
@@ -1,9 +1,54 @@
|
|||||||
# TelegramBotAPI changelog
|
# TelegramBotAPI changelog
|
||||||
|
|
||||||
|
## 6.0.3
|
||||||
|
|
||||||
|
* `Versions`:
|
||||||
|
* `MicroUtils`: `0.17.1` -> `0.17.2`
|
||||||
|
* `Core`:
|
||||||
|
* `User` in `CallbackQuery` now is `CommonUser` as well as in `from`
|
||||||
|
* `User` in `InlineQuery` now is `CommonUser` as well as in `from`
|
||||||
|
* `BehaviourBuilder`:
|
||||||
|
* Fixes in `DeepLink` triggers and waiters
|
||||||
|
|
||||||
|
## 6.0.2
|
||||||
|
|
||||||
|
* `Core`:
|
||||||
|
* Long polling now uses media groups debounce as in webhooks
|
||||||
|
|
||||||
|
## 6.0.1
|
||||||
|
|
||||||
|
* `Versions`:
|
||||||
|
* `Ktor`: `2.2.3` -> `2.2.4`
|
||||||
|
* `MicroUtils`: `0.17.0` -> `0.17.1`
|
||||||
|
|
||||||
|
## 6.0.0
|
||||||
|
|
||||||
|
* `Versions`:
|
||||||
|
* `Kotlin`: `1.7.22` -> `1.8.10`
|
||||||
|
* `MicroUtils`: `0.16.10` -> `0.17.0`
|
||||||
|
* `Serialization`: `1.4.1` -> `1.5.0`
|
||||||
|
* `uuid`: `0.6.0` -> `0.7.0`
|
||||||
|
* `Core`:
|
||||||
|
* `*.link` extensions have been deprecated with renaming to avoid collisions with `link` methods
|
||||||
|
* `API`:
|
||||||
|
* Add `TelegramBot.resend` methods
|
||||||
|
* `BehaviourBuilder`:
|
||||||
|
* Add triggers and waiters for `VisualMediaGroupPartContent`
|
||||||
|
* `Utils`:
|
||||||
|
* `*.link` extensions have been deprecated with renaming to avoid collisions with `link` methods
|
||||||
|
|
||||||
|
## 5.2.1
|
||||||
|
|
||||||
|
* `Core`:
|
||||||
|
* All the `CallbackQuery`es now will receive `CommonUser` instead of `User` due inability of bots to trigger any
|
||||||
|
inline interaction with others bots
|
||||||
|
* `API`:
|
||||||
|
* Now `sentMessageFlow` will take each sent message in `handleLiveLocation`
|
||||||
|
|
||||||
## 5.2.0
|
## 5.2.0
|
||||||
|
|
||||||
* `Versions`:
|
* `Versions`:
|
||||||
* `MicroUtils`: `0.16.8` -> `0.16.10`
|
* `MicroUtils`: `0.16.8` -> `0.16.10`
|
||||||
|
|
||||||
## 5.1.1
|
## 5.1.1
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
| Useful repos | [](https://github.com/InsanusMokrassar/TelegramBotAPI-bot_template/generate) [](https://github.com/InsanusMokrassar/TelegramBotAPI-examples/) |
|
| Useful repos | [](https://github.com/InsanusMokrassar/TelegramBotAPI-bot_template/generate) [](https://github.com/InsanusMokrassar/TelegramBotAPI-examples/) |
|
||||||
| Misc | [](https://github.com/KotlinBy/awesome-kotlin) [](https://docs.google.com/forms/d/e/1FAIpQLSctdJHT_aEniyYT0-IUAEfo1hsIlezX2owlkEAYX4KPl2V2_A/viewform?usp=sf_link) |
|
| Misc | [](https://github.com/KotlinBy/awesome-kotlin) [](https://docs.google.com/forms/d/e/1FAIpQLSctdJHT_aEniyYT0-IUAEfo1hsIlezX2owlkEAYX4KPl2V2_A/viewform?usp=sf_link) |
|
||||||
|
|
||||||
<!--- [](https://t.me/InMoTelegramBotAPI) --->
|
<!--- [](https://t.me/ktgbotapi) --->
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://t.me/InMoTelegramBotAPI">
|
<a href="https://t.me/ktgbotapi">
|
||||||
<img src="./resources/tg_channel_qr.jpg">
|
<img src="./resources/tg_channel_qr.jpg">
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -6,4 +6,4 @@ kotlin.incremental=true
|
|||||||
kotlin.incremental.js=true
|
kotlin.incremental.js=true
|
||||||
|
|
||||||
library_group=dev.inmo
|
library_group=dev.inmo
|
||||||
library_version=5.2.0
|
library_version=6.0.3
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
[versions]
|
[versions]
|
||||||
|
|
||||||
kotlin = "1.7.22"
|
kotlin = "1.8.10"
|
||||||
kotlin-serialization = "1.4.1"
|
kotlin-serialization = "1.5.0"
|
||||||
kotlin-coroutines = "1.6.4"
|
kotlin-coroutines = "1.6.4"
|
||||||
|
|
||||||
javax-activation = "1.1.1"
|
javax-activation = "1.1.1"
|
||||||
|
|
||||||
korlibs = "3.4.0"
|
korlibs = "3.4.0"
|
||||||
uuid = "0.6.0"
|
uuid = "0.7.0"
|
||||||
ktor = "2.2.3"
|
ktor = "2.2.4"
|
||||||
|
|
||||||
ksp = "1.7.22-1.0.8"
|
ksp = "1.8.10-1.0.9"
|
||||||
kotlin-poet = "1.12.0"
|
kotlin-poet = "1.12.0"
|
||||||
|
|
||||||
microutils = "0.16.10"
|
microutils = "0.17.2"
|
||||||
|
|
||||||
github-release-plugin = "2.4.1"
|
github-release-plugin = "2.4.1"
|
||||||
dokka = "1.7.20"
|
dokka = "1.7.20"
|
||||||
|
|||||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
apply plugin: 'maven-publish'
|
apply plugin: 'maven-publish'
|
||||||
|
|
||||||
task javadocsJar(type: Jar) {
|
task javadocsJar(type: Jar) {
|
||||||
classifier = 'javadoc'
|
archiveClassifier.convention("javadoc")
|
||||||
|
archiveClassifier.set("javadoc")
|
||||||
}
|
}
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
@@ -19,22 +20,22 @@ publishing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
developers {
|
developers {
|
||||||
|
|
||||||
developer {
|
developer {
|
||||||
id = "InsanusMokrassar"
|
id = "InsanusMokrassar"
|
||||||
name = "Ovsiannikov Aleksei"
|
name = "Ovsiannikov Aleksei"
|
||||||
email = "ovsyannikov.alexey95@gmail.com"
|
email = "ovsyannikov.alexey95@gmail.com"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
licenses {
|
licenses {
|
||||||
|
|
||||||
license {
|
license {
|
||||||
name = "Apache Software License 2.0"
|
name = "Apache Software License 2.0"
|
||||||
url = "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
|
url = "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
repositories {
|
repositories {
|
||||||
@@ -42,55 +43,55 @@ publishing {
|
|||||||
maven {
|
maven {
|
||||||
name = "GithubPackages"
|
name = "GithubPackages"
|
||||||
url = uri("https://maven.pkg.github.com/InsanusMokrassar/TelegramBotAPI")
|
url = uri("https://maven.pkg.github.com/InsanusMokrassar/TelegramBotAPI")
|
||||||
|
|
||||||
credentials {
|
credentials {
|
||||||
username = project.hasProperty('GITHUBPACKAGES_USER') ? project.property('GITHUBPACKAGES_USER') : System.getenv('GITHUBPACKAGES_USER')
|
username = project.hasProperty('GITHUBPACKAGES_USER') ? project.property('GITHUBPACKAGES_USER') : System.getenv('GITHUBPACKAGES_USER')
|
||||||
password = project.hasProperty('GITHUBPACKAGES_PASSWORD') ? project.property('GITHUBPACKAGES_PASSWORD') : System.getenv('GITHUBPACKAGES_PASSWORD')
|
password = project.hasProperty('GITHUBPACKAGES_PASSWORD') ? project.property('GITHUBPACKAGES_PASSWORD') : System.getenv('GITHUBPACKAGES_PASSWORD')
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (project.hasProperty('GITEA_TOKEN') || System.getenv('GITEA_TOKEN') != null) {
|
if (project.hasProperty('GITEA_TOKEN') || System.getenv('GITEA_TOKEN') != null) {
|
||||||
maven {
|
maven {
|
||||||
name = "Gitea"
|
name = "Gitea"
|
||||||
url = uri("https://git.inmo.dev/api/packages/InsanusMokrassar/maven")
|
url = uri("https://git.inmo.dev/api/packages/InsanusMokrassar/maven")
|
||||||
|
|
||||||
credentials(HttpHeaderCredentials) {
|
credentials(HttpHeaderCredentials) {
|
||||||
name = "Authorization"
|
name = "Authorization"
|
||||||
value = project.hasProperty('GITEA_TOKEN') ? project.property('GITEA_TOKEN') : System.getenv('GITEA_TOKEN')
|
value = project.hasProperty('GITEA_TOKEN') ? project.property('GITEA_TOKEN') : System.getenv('GITEA_TOKEN')
|
||||||
}
|
}
|
||||||
|
|
||||||
authentication {
|
authentication {
|
||||||
header(HttpHeaderAuthentication)
|
header(HttpHeaderAuthentication)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((project.hasProperty('SONATYPE_USER') || System.getenv('SONATYPE_USER') != null) && (project.hasProperty('SONATYPE_PASSWORD') || System.getenv('SONATYPE_PASSWORD') != null)) {
|
if ((project.hasProperty('SONATYPE_USER') || System.getenv('SONATYPE_USER') != null) && (project.hasProperty('SONATYPE_PASSWORD') || System.getenv('SONATYPE_PASSWORD') != null)) {
|
||||||
maven {
|
maven {
|
||||||
name = "sonatype"
|
name = "sonatype"
|
||||||
url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2/")
|
url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2/")
|
||||||
|
|
||||||
credentials {
|
credentials {
|
||||||
username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER')
|
username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER')
|
||||||
password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD')
|
password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD')
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (project.hasProperty("signing.gnupg.keyName")) {
|
if (project.hasProperty("signing.gnupg.keyName")) {
|
||||||
apply plugin: 'signing'
|
apply plugin: 'signing'
|
||||||
|
|
||||||
signing {
|
signing {
|
||||||
useGpgCmd()
|
useGpgCmd()
|
||||||
|
|
||||||
sign publishing.publications
|
sign publishing.publications
|
||||||
}
|
}
|
||||||
|
|
||||||
task signAll {
|
task signAll {
|
||||||
tasks.withType(Sign).forEach {
|
tasks.withType(Sign).forEach {
|
||||||
dependsOn(it)
|
dependsOn(it)
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 593 KiB After Width: | Height: | Size: 448 KiB |
@@ -86,7 +86,9 @@ suspend fun TelegramBot.handleLiveLocation(
|
|||||||
it.heading,
|
it.heading,
|
||||||
it.proximityAlertRadius,
|
it.proximityAlertRadius,
|
||||||
it.replyMarkup
|
it.replyMarkup
|
||||||
)
|
).also {
|
||||||
|
sentMessageFlow ?.emit(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
package dev.inmo.tgbotapi.extensions.api.send
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||||
|
import dev.inmo.tgbotapi.types.ChatIdentifier
|
||||||
|
import dev.inmo.tgbotapi.types.MessageId
|
||||||
|
import dev.inmo.tgbotapi.types.MessageThreadId
|
||||||
|
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
|
||||||
|
import dev.inmo.tgbotapi.types.chat.Chat
|
||||||
|
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||||
|
import dev.inmo.tgbotapi.types.message.content.MessageContent
|
||||||
|
import dev.inmo.tgbotapi.types.threadId
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will send [content] to the [chatId] as is
|
||||||
|
*/
|
||||||
|
suspend inline fun <T : MessageContent> TelegramBot.resend(
|
||||||
|
chatId: ChatIdentifier,
|
||||||
|
content: T,
|
||||||
|
messageThreadId: MessageThreadId? = chatId.threadId,
|
||||||
|
disableNotification: Boolean = false,
|
||||||
|
protectContent: Boolean = false,
|
||||||
|
replyToMessageId: MessageId? = null,
|
||||||
|
allowSendingWithoutReply: Boolean? = null,
|
||||||
|
replyMarkup: KeyboardMarkup? = null
|
||||||
|
) = execute(
|
||||||
|
content.createResend(
|
||||||
|
chatId = chatId,
|
||||||
|
messageThreadId = messageThreadId,
|
||||||
|
disableNotification = disableNotification,
|
||||||
|
protectContent = protectContent,
|
||||||
|
replyToMessageId = replyToMessageId,
|
||||||
|
allowSendingWithoutReply = allowSendingWithoutReply,
|
||||||
|
replyMarkup = replyMarkup
|
||||||
|
)
|
||||||
|
) as ContentMessage<T>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will send [content] to the [chatId] as is
|
||||||
|
*/
|
||||||
|
suspend inline fun <T : MessageContent> TelegramBot.resend(
|
||||||
|
chat: Chat,
|
||||||
|
content: T,
|
||||||
|
messageThreadId: MessageThreadId? = chat.id.threadId,
|
||||||
|
disableNotification: Boolean = false,
|
||||||
|
protectContent: Boolean = false,
|
||||||
|
replyToMessageId: MessageId? = null,
|
||||||
|
allowSendingWithoutReply: Boolean? = null,
|
||||||
|
replyMarkup: KeyboardMarkup? = null
|
||||||
|
) = resend(
|
||||||
|
chatId = chat.id,
|
||||||
|
content = content,
|
||||||
|
messageThreadId = messageThreadId,
|
||||||
|
disableNotification = disableNotification,
|
||||||
|
protectContent = protectContent,
|
||||||
|
replyToMessageId = replyToMessageId,
|
||||||
|
allowSendingWithoutReply = allowSendingWithoutReply,
|
||||||
|
replyMarkup = replyMarkup
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will send [message] content to the [chatId]. In difference with [copyMessage], this method will use
|
||||||
|
* native methods for data sending (like [dev.inmo.tgbotapi.extensions.api.send.media.sendPhoto] if inoming content is
|
||||||
|
* [dev.inmo.tgbotapi.types.message.content.PhotoContent])
|
||||||
|
*/
|
||||||
|
suspend inline fun <T : MessageContent> TelegramBot.resend(
|
||||||
|
chatId: ChatIdentifier,
|
||||||
|
message: ContentMessage<T>,
|
||||||
|
messageThreadId: MessageThreadId? = chatId.threadId,
|
||||||
|
disableNotification: Boolean = false,
|
||||||
|
protectContent: Boolean = false,
|
||||||
|
replyToMessageId: MessageId? = null,
|
||||||
|
allowSendingWithoutReply: Boolean? = null,
|
||||||
|
replyMarkup: KeyboardMarkup? = null
|
||||||
|
) = resend(
|
||||||
|
chatId = chatId,
|
||||||
|
content = message.content,
|
||||||
|
messageThreadId = messageThreadId,
|
||||||
|
disableNotification = disableNotification,
|
||||||
|
protectContent = protectContent,
|
||||||
|
replyToMessageId = replyToMessageId,
|
||||||
|
allowSendingWithoutReply = allowSendingWithoutReply,
|
||||||
|
replyMarkup = replyMarkup
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will send [message] content to the [chat]. In difference with [copyMessage], this method will use
|
||||||
|
* native methods for data sending (like [dev.inmo.tgbotapi.extensions.api.send.media.sendPhoto] if inoming content is
|
||||||
|
* [dev.inmo.tgbotapi.types.message.content.PhotoContent])
|
||||||
|
*/
|
||||||
|
suspend inline fun <T : MessageContent> TelegramBot.resend(
|
||||||
|
chat: Chat,
|
||||||
|
message: ContentMessage<T>,
|
||||||
|
messageThreadId: MessageThreadId? = chat.id.threadId,
|
||||||
|
disableNotification: Boolean = false,
|
||||||
|
protectContent: Boolean = false,
|
||||||
|
replyToMessageId: MessageId? = null,
|
||||||
|
allowSendingWithoutReply: Boolean? = null,
|
||||||
|
replyMarkup: KeyboardMarkup? = null
|
||||||
|
) = resend(
|
||||||
|
chatId = chat.id,
|
||||||
|
message = message,
|
||||||
|
messageThreadId = messageThreadId,
|
||||||
|
disableNotification = disableNotification,
|
||||||
|
protectContent = protectContent,
|
||||||
|
replyToMessageId = replyToMessageId,
|
||||||
|
allowSendingWithoutReply = allowSendingWithoutReply,
|
||||||
|
replyMarkup = replyMarkup
|
||||||
|
)
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
package dev.inmo.tgbotapi.extensions.api.utils
|
package dev.inmo.tgbotapi.extensions.api.utils
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions
|
||||||
import dev.inmo.tgbotapi.extensions.api.InternalUtils.convertWithMediaGroupUpdates
|
import dev.inmo.tgbotapi.extensions.api.InternalUtils.convertWithMediaGroupUpdates
|
||||||
import dev.inmo.tgbotapi.types.message.abstracts.PossiblySentViaBotCommonMessage
|
import dev.inmo.tgbotapi.types.message.abstracts.PossiblyMediaGroupMessage
|
||||||
import dev.inmo.tgbotapi.types.update.abstracts.BaseMessageUpdate
|
import dev.inmo.tgbotapi.types.update.abstracts.BaseMessageUpdate
|
||||||
import dev.inmo.tgbotapi.types.update.abstracts.Update
|
import dev.inmo.tgbotapi.types.update.abstracts.Update
|
||||||
import dev.inmo.tgbotapi.updateshandlers.UpdateReceiver
|
import dev.inmo.tgbotapi.updateshandlers.UpdateReceiver
|
||||||
@@ -28,26 +29,18 @@ fun CoroutineScope.updateHandlerWithMediaGroupsAdaptation(
|
|||||||
)
|
)
|
||||||
|
|
||||||
launch {
|
launch {
|
||||||
launch {
|
launchSafelyWithoutExceptions {
|
||||||
for (update in updatesChannel) {
|
for (update in updatesChannel) {
|
||||||
val dataAsPossiblySentViaBotCommonMessage = update.data as? PossiblySentViaBotCommonMessage<*>
|
val data = update.data
|
||||||
|
when {
|
||||||
if (dataAsPossiblySentViaBotCommonMessage == null) {
|
data is PossiblyMediaGroupMessage<*> && data.mediaGroupId != null -> {
|
||||||
output(update)
|
mediaGroupChannel.send("${data.mediaGroupId}${update::class.simpleName}" to update as BaseMessageUpdate)
|
||||||
continue
|
}
|
||||||
|
else -> output(update)
|
||||||
}
|
}
|
||||||
|
|
||||||
val mediaGroupId = dataAsPossiblySentViaBotCommonMessage.mediaGroupId
|
|
||||||
|
|
||||||
if (mediaGroupId == null) {
|
|
||||||
output(update)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
mediaGroupChannel.send("${mediaGroupId}${update::class.simpleName}" to update as BaseMessageUpdate)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
launch {
|
launchSafelyWithoutExceptions {
|
||||||
for ((_, mediaGroup) in mediaGroupAccumulatedChannel) {
|
for ((_, mediaGroup) in mediaGroupAccumulatedChannel) {
|
||||||
mediaGroup.convertWithMediaGroupUpdates().forEach {
|
mediaGroup.convertWithMediaGroupUpdates().forEach {
|
||||||
output(it)
|
output(it)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import dev.inmo.micro_utils.fsm.common.utils.StateHandlingErrorHandler
|
|||||||
import dev.inmo.micro_utils.fsm.common.utils.defaultStateHandlingErrorHandler
|
import dev.inmo.micro_utils.fsm.common.utils.defaultStateHandlingErrorHandler
|
||||||
import dev.inmo.tgbotapi.bot.TelegramBot
|
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||||
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.longPolling
|
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.longPolling
|
||||||
|
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.updateHandlerWithMediaGroupsAdaptation
|
||||||
import dev.inmo.tgbotapi.types.Seconds
|
import dev.inmo.tgbotapi.types.Seconds
|
||||||
import dev.inmo.tgbotapi.types.update.abstracts.Update
|
import dev.inmo.tgbotapi.types.update.abstracts.Update
|
||||||
import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
|
import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
|
||||||
@@ -47,6 +48,10 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSM(
|
|||||||
* Use [buildBehaviourWithFSM] to create [BehaviourContextWithFSM] and launch getting of updates
|
* Use [buildBehaviourWithFSM] to create [BehaviourContextWithFSM] and launch getting of updates
|
||||||
* using [longPolling]. For [longPolling] will be used result [BehaviourContextWithFSM] for both parameters
|
* using [longPolling]. For [longPolling] will be used result [BehaviourContextWithFSM] for both parameters
|
||||||
* flowsUpdatesFilter and scope
|
* flowsUpdatesFilter and scope
|
||||||
|
*
|
||||||
|
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
|
||||||
|
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
|
||||||
|
* retrieved in different updates
|
||||||
*/
|
*/
|
||||||
suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
|
suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
|
||||||
upstreamUpdatesFlow: Flow<Update>? = null,
|
upstreamUpdatesFlow: Flow<Update>? = null,
|
||||||
@@ -58,6 +63,7 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
|
|||||||
timeoutSeconds: Seconds = 30,
|
timeoutSeconds: Seconds = 30,
|
||||||
autoDisableWebhooks: Boolean = true,
|
autoDisableWebhooks: Boolean = true,
|
||||||
autoSkipTimeoutExceptions: Boolean = true,
|
autoSkipTimeoutExceptions: Boolean = true,
|
||||||
|
mediaGroupsDebounceTimeMillis: Long? = 1000L,
|
||||||
block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit>
|
block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit>
|
||||||
): Pair<DefaultBehaviourContextWithFSM<T>, Job> = buildBehaviourWithFSM(
|
): Pair<DefaultBehaviourContextWithFSM<T>, Job> = buildBehaviourWithFSM(
|
||||||
upstreamUpdatesFlow,
|
upstreamUpdatesFlow,
|
||||||
@@ -70,7 +76,7 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
|
|||||||
).run {
|
).run {
|
||||||
this to scope.launch {
|
this to scope.launch {
|
||||||
start()
|
start()
|
||||||
longPolling(flowsUpdatesFilter, timeoutSeconds, scope, autoDisableWebhooks, autoSkipTimeoutExceptions, defaultExceptionsHandler)
|
longPolling(flowsUpdatesFilter, timeoutSeconds, scope, autoDisableWebhooks, autoSkipTimeoutExceptions, mediaGroupsDebounceTimeMillis, defaultExceptionsHandler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,6 +122,10 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSM(
|
|||||||
* using [longPolling]. For [longPolling] will be used result [BehaviourContextWithFSM] for both parameters
|
* using [longPolling]. For [longPolling] will be used result [BehaviourContextWithFSM] for both parameters
|
||||||
* flowsUpdatesFilter and scope
|
* flowsUpdatesFilter and scope
|
||||||
*
|
*
|
||||||
|
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
|
||||||
|
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
|
||||||
|
* retrieved in different updates
|
||||||
|
*
|
||||||
* @see buildBehaviourWithFSMAndStartLongPolling
|
* @see buildBehaviourWithFSMAndStartLongPolling
|
||||||
* @see BehaviourContext
|
* @see BehaviourContext
|
||||||
* @see longPolling
|
* @see longPolling
|
||||||
@@ -131,6 +141,7 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
|
|||||||
timeoutSeconds: Seconds = 30,
|
timeoutSeconds: Seconds = 30,
|
||||||
autoDisableWebhooks: Boolean = true,
|
autoDisableWebhooks: Boolean = true,
|
||||||
autoSkipTimeoutExceptions: Boolean = true,
|
autoSkipTimeoutExceptions: Boolean = true,
|
||||||
|
mediaGroupsDebounceTimeMillis: Long? = 1000L,
|
||||||
block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit>
|
block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit>
|
||||||
) = FlowsUpdatesFilter().let {
|
) = FlowsUpdatesFilter().let {
|
||||||
buildBehaviourWithFSM(
|
buildBehaviourWithFSM(
|
||||||
@@ -149,6 +160,7 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
|
|||||||
scope,
|
scope,
|
||||||
autoDisableWebhooks,
|
autoDisableWebhooks,
|
||||||
autoSkipTimeoutExceptions,
|
autoSkipTimeoutExceptions,
|
||||||
|
mediaGroupsDebounceTimeMillis,
|
||||||
defaultExceptionsHandler
|
defaultExceptionsHandler
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import dev.inmo.tgbotapi.bot.ktor.KtorRequestsExecutorBuilder
|
|||||||
import dev.inmo.tgbotapi.bot.ktor.telegramBot
|
import dev.inmo.tgbotapi.bot.ktor.telegramBot
|
||||||
import dev.inmo.tgbotapi.bot.TelegramBot
|
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||||
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.startGettingOfUpdatesByLongPolling
|
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.startGettingOfUpdatesByLongPolling
|
||||||
|
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.updateHandlerWithMediaGroupsAdaptation
|
||||||
import dev.inmo.tgbotapi.types.Seconds
|
import dev.inmo.tgbotapi.types.Seconds
|
||||||
import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
|
import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
|
||||||
import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl
|
import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl
|
||||||
@@ -26,6 +27,10 @@ import kotlin.coroutines.coroutineContext
|
|||||||
* **WARNING** This method WILL NOT launch any listening of updates. Use something like
|
* **WARNING** This method WILL NOT launch any listening of updates. Use something like
|
||||||
* [startGettingOfUpdatesByLongPolling] or tools for work with webhooks
|
* [startGettingOfUpdatesByLongPolling] or tools for work with webhooks
|
||||||
*
|
*
|
||||||
|
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
|
||||||
|
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
|
||||||
|
* retrieved in different updates
|
||||||
|
*
|
||||||
* @return Created bot which has been used to create [BehaviourContext] via [buildBehaviourWithFSM]
|
* @return Created bot which has been used to create [BehaviourContext] via [buildBehaviourWithFSM]
|
||||||
*
|
*
|
||||||
* @see [BehaviourContext]
|
* @see [BehaviourContext]
|
||||||
@@ -46,6 +51,7 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSM(
|
|||||||
timeoutSeconds: Seconds = 30,
|
timeoutSeconds: Seconds = 30,
|
||||||
autoDisableWebhooks: Boolean = true,
|
autoDisableWebhooks: Boolean = true,
|
||||||
autoSkipTimeoutExceptions: Boolean = true,
|
autoSkipTimeoutExceptions: Boolean = true,
|
||||||
|
mediaGroupsDebounceTimeMillis: Long? = 1000L,
|
||||||
block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit>
|
block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit>
|
||||||
): TelegramBot = telegramBot(
|
): TelegramBot = telegramBot(
|
||||||
token,
|
token,
|
||||||
@@ -63,6 +69,7 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSM(
|
|||||||
timeoutSeconds,
|
timeoutSeconds,
|
||||||
autoDisableWebhooks,
|
autoDisableWebhooks,
|
||||||
autoSkipTimeoutExceptions,
|
autoSkipTimeoutExceptions,
|
||||||
|
mediaGroupsDebounceTimeMillis,
|
||||||
block
|
block
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -71,6 +78,10 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSM(
|
|||||||
* Create bot using [telegramBot] and start listening for updates using [buildBehaviourWithFSMAndStartLongPolling]. This
|
* Create bot using [telegramBot] and start listening for updates using [buildBehaviourWithFSMAndStartLongPolling]. This
|
||||||
* method will launch updates retrieving via long polling inside of [buildBehaviourWithFSMAndStartLongPolling]
|
* method will launch updates retrieving via long polling inside of [buildBehaviourWithFSMAndStartLongPolling]
|
||||||
*
|
*
|
||||||
|
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
|
||||||
|
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
|
||||||
|
* retrieved in different updates
|
||||||
|
*
|
||||||
* @return Pair of [TelegramBot] and [Job]. This [Job] can be used to stop listening updates in your [block] you passed
|
* @return Pair of [TelegramBot] and [Job]. This [Job] can be used to stop listening updates in your [block] you passed
|
||||||
* here
|
* here
|
||||||
*
|
*
|
||||||
@@ -91,6 +102,7 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSMAndStartLongPolling(
|
|||||||
timeoutSeconds: Seconds = 30,
|
timeoutSeconds: Seconds = 30,
|
||||||
autoDisableWebhooks: Boolean = true,
|
autoDisableWebhooks: Boolean = true,
|
||||||
autoSkipTimeoutExceptions: Boolean = true,
|
autoSkipTimeoutExceptions: Boolean = true,
|
||||||
|
mediaGroupsDebounceTimeMillis: Long? = 1000L,
|
||||||
block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit>
|
block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit>
|
||||||
): Pair<TelegramBot, Job> {
|
): Pair<TelegramBot, Job> {
|
||||||
return telegramBot(
|
return telegramBot(
|
||||||
@@ -108,6 +120,7 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSMAndStartLongPolling(
|
|||||||
timeoutSeconds,
|
timeoutSeconds,
|
||||||
autoDisableWebhooks,
|
autoDisableWebhooks,
|
||||||
autoSkipTimeoutExceptions,
|
autoSkipTimeoutExceptions,
|
||||||
|
mediaGroupsDebounceTimeMillis,
|
||||||
block
|
block
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import dev.inmo.micro_utils.coroutines.ExceptionHandler
|
|||||||
import dev.inmo.tgbotapi.bot.TelegramBot
|
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||||
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.longPolling
|
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.longPolling
|
||||||
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.startGettingOfUpdatesByLongPolling
|
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.startGettingOfUpdatesByLongPolling
|
||||||
|
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.updateHandlerWithMediaGroupsAdaptation
|
||||||
import dev.inmo.tgbotapi.types.Seconds
|
import dev.inmo.tgbotapi.types.Seconds
|
||||||
import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
|
import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
@@ -47,6 +48,10 @@ suspend fun TelegramBot.buildBehaviour(
|
|||||||
* Use this method to build bot behaviour and run it via long polling. In case you wish to get [FlowsUpdatesFilter] for
|
* Use this method to build bot behaviour and run it via long polling. In case you wish to get [FlowsUpdatesFilter] for
|
||||||
* additional manipulations, you must provide external [FlowsUpdatesFilter] in other [buildBehaviour] function.
|
* additional manipulations, you must provide external [FlowsUpdatesFilter] in other [buildBehaviour] function.
|
||||||
*
|
*
|
||||||
|
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
|
||||||
|
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
|
||||||
|
* retrieved in different updates
|
||||||
|
*
|
||||||
* @see buildBehaviour
|
* @see buildBehaviour
|
||||||
* @see BehaviourContext
|
* @see BehaviourContext
|
||||||
* @see startGettingOfUpdatesByLongPolling
|
* @see startGettingOfUpdatesByLongPolling
|
||||||
@@ -57,6 +62,7 @@ suspend fun TelegramBot.buildBehaviourWithLongPolling(
|
|||||||
timeoutSeconds: Seconds = 30,
|
timeoutSeconds: Seconds = 30,
|
||||||
autoDisableWebhooks: Boolean = true,
|
autoDisableWebhooks: Boolean = true,
|
||||||
autoSkipTimeoutExceptions: Boolean = true,
|
autoSkipTimeoutExceptions: Boolean = true,
|
||||||
|
mediaGroupsDebounceTimeMillis: Long? = 1000L,
|
||||||
block: BehaviourContextReceiver<Unit>
|
block: BehaviourContextReceiver<Unit>
|
||||||
): Job {
|
): Job {
|
||||||
val behaviourContext = buildBehaviour(
|
val behaviourContext = buildBehaviour(
|
||||||
@@ -69,6 +75,7 @@ suspend fun TelegramBot.buildBehaviourWithLongPolling(
|
|||||||
scope = behaviourContext,
|
scope = behaviourContext,
|
||||||
timeoutSeconds = timeoutSeconds,
|
timeoutSeconds = timeoutSeconds,
|
||||||
autoDisableWebhooks = autoDisableWebhooks,
|
autoDisableWebhooks = autoDisableWebhooks,
|
||||||
autoSkipTimeoutExceptions = autoSkipTimeoutExceptions
|
autoSkipTimeoutExceptions = autoSkipTimeoutExceptions,
|
||||||
|
mediaGroupsDebounceTimeMillis = mediaGroupsDebounceTimeMillis
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import dev.inmo.tgbotapi.bot.TelegramBot
|
|||||||
import dev.inmo.tgbotapi.bot.ktor.KtorRequestsExecutorBuilder
|
import dev.inmo.tgbotapi.bot.ktor.KtorRequestsExecutorBuilder
|
||||||
import dev.inmo.tgbotapi.bot.ktor.telegramBot
|
import dev.inmo.tgbotapi.bot.ktor.telegramBot
|
||||||
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.startGettingOfUpdatesByLongPolling
|
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.startGettingOfUpdatesByLongPolling
|
||||||
|
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.updateHandlerWithMediaGroupsAdaptation
|
||||||
import dev.inmo.tgbotapi.types.Seconds
|
import dev.inmo.tgbotapi.types.Seconds
|
||||||
import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
|
import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
|
||||||
import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl
|
import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl
|
||||||
@@ -53,6 +54,10 @@ suspend fun telegramBotWithBehaviour(
|
|||||||
*
|
*
|
||||||
* **WARNING** This method WILL launch updates listening inside of calling [buildBehaviourWithLongPolling]
|
* **WARNING** This method WILL launch updates listening inside of calling [buildBehaviourWithLongPolling]
|
||||||
*
|
*
|
||||||
|
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
|
||||||
|
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
|
||||||
|
* retrieved in different updates
|
||||||
|
*
|
||||||
* @return Pair of [TelegramBot] and [Job]. This [Job] can be used to stop listening updates in your [block] you passed
|
* @return Pair of [TelegramBot] and [Job]. This [Job] can be used to stop listening updates in your [block] you passed
|
||||||
* here
|
* here
|
||||||
*
|
*
|
||||||
@@ -70,6 +75,7 @@ suspend fun telegramBotWithBehaviourAndLongPolling(
|
|||||||
timeoutSeconds: Seconds = 30,
|
timeoutSeconds: Seconds = 30,
|
||||||
autoDisableWebhooks: Boolean = true,
|
autoDisableWebhooks: Boolean = true,
|
||||||
autoSkipTimeoutExceptions: Boolean = true,
|
autoSkipTimeoutExceptions: Boolean = true,
|
||||||
|
mediaGroupsDebounceTimeMillis: Long? = 1000L,
|
||||||
block: BehaviourContextReceiver<Unit>
|
block: BehaviourContextReceiver<Unit>
|
||||||
): Pair<TelegramBot, Job> {
|
): Pair<TelegramBot, Job> {
|
||||||
return telegramBot(
|
return telegramBot(
|
||||||
@@ -84,6 +90,7 @@ suspend fun telegramBotWithBehaviourAndLongPolling(
|
|||||||
timeoutSeconds,
|
timeoutSeconds,
|
||||||
autoDisableWebhooks,
|
autoDisableWebhooks,
|
||||||
autoSkipTimeoutExceptions,
|
autoSkipTimeoutExceptions,
|
||||||
|
mediaGroupsDebounceTimeMillis,
|
||||||
block
|
block
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -189,3 +189,7 @@ suspend fun BehaviourContext.waitInvoice(
|
|||||||
initRequest: Request<*>? = null,
|
initRequest: Request<*>? = null,
|
||||||
errorFactory: NullableRequestBuilder<*> = { null }
|
errorFactory: NullableRequestBuilder<*> = { null }
|
||||||
) = waitContent<InvoiceContent>(initRequest, errorFactory)
|
) = waitContent<InvoiceContent>(initRequest, errorFactory)
|
||||||
|
suspend fun BehaviourContext.waitVisualContent(
|
||||||
|
initRequest: Request<*>? = null,
|
||||||
|
errorFactory: NullableRequestBuilder<*> = { null }
|
||||||
|
) = waitContent<VisualMediaGroupPartContent>(initRequest, errorFactory)
|
||||||
|
|||||||
@@ -216,3 +216,8 @@ suspend fun BehaviourContext.waitInvoiceMessage(
|
|||||||
initRequest: Request<*>? = null,
|
initRequest: Request<*>? = null,
|
||||||
errorFactory: NullableRequestBuilder<*> = { null }
|
errorFactory: NullableRequestBuilder<*> = { null }
|
||||||
) = waitContentMessage<InvoiceContent>(initRequest, errorFactory)
|
) = waitContentMessage<InvoiceContent>(initRequest, errorFactory)
|
||||||
|
|
||||||
|
suspend fun BehaviourContext.waitVisualContentMessage(
|
||||||
|
initRequest: Request<*>? = null,
|
||||||
|
errorFactory: NullableRequestBuilder<*> = { null }
|
||||||
|
) = waitContentMessage<VisualMediaGroupPartContent>(initRequest, errorFactory)
|
||||||
|
|||||||
@@ -607,3 +607,27 @@ suspend fun <BC : BehaviourContext> BC.onInvoice(
|
|||||||
markerFactory,
|
markerFactory,
|
||||||
scenarioReceiver
|
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.onVisualContent(
|
||||||
|
initialFilter: CommonMessageFilter<VisualMediaGroupPartContent>? = null,
|
||||||
|
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, VisualMediaGroupMessage, Update> = MessageFilterByChat,
|
||||||
|
markerFactory: MarkerFactory<in VisualMediaGroupMessage, Any> = ByChatMessageMarkerFactory,
|
||||||
|
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, VisualMediaGroupMessage>
|
||||||
|
) = onContentMessageWithType(
|
||||||
|
initialFilter,
|
||||||
|
subcontextUpdatesFilter,
|
||||||
|
markerFactory,
|
||||||
|
scenarioReceiver
|
||||||
|
)
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ suspend fun <BC : BehaviourContext> BC.onDeepLink(
|
|||||||
scenarioReceiver,
|
scenarioReceiver,
|
||||||
) {
|
) {
|
||||||
(it.messageUpdateOrNull()) ?.data ?.commonMessageOrNull() ?.withContentOrNull<TextContent>() ?.let { message ->
|
(it.messageUpdateOrNull()) ?.data ?.commonMessageOrNull() ?.withContentOrNull<TextContent>() ?.let { message ->
|
||||||
message to message.content.textSources[1].source.removePrefix(" ").decodeURLQueryComponent()
|
message to (message.content.textSources.getOrNull(1) ?.source ?.removePrefix(" ") ?.decodeURLQueryComponent() ?: return@let null)
|
||||||
} ?.let(::listOfNotNull)
|
} ?.let(::listOfNotNull)
|
||||||
}.also {
|
}.also {
|
||||||
triggersHolder.handleableCommandsHolder.registerHandleable(startRegex)
|
triggersHolder.handleableCommandsHolder.registerHandleable(startRegex)
|
||||||
|
|||||||
@@ -74,8 +74,11 @@ val Identifier.userLink: String
|
|||||||
@Warning("This API have restrictions in Telegram System")
|
@Warning("This API have restrictions in Telegram System")
|
||||||
val UserId.userLink: String
|
val UserId.userLink: String
|
||||||
get() = chatId.userLink
|
get() = chatId.userLink
|
||||||
val User.link: String
|
val User.userLink: String
|
||||||
get() = id.userLink
|
get() = id.userLink
|
||||||
|
@Deprecated("Deprecated due to the conflicts in name", ReplaceWith("this.userLink", "dev.inmo.tgbotapi.types.userLink"))
|
||||||
|
val User.link: String
|
||||||
|
get() = userLink
|
||||||
|
|
||||||
typealias UserId = ChatId
|
typealias UserId = ChatId
|
||||||
|
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ package dev.inmo.tgbotapi.types.InlineQueries.query
|
|||||||
import dev.inmo.tgbotapi.types.InlineQueryIdentifier
|
import dev.inmo.tgbotapi.types.InlineQueryIdentifier
|
||||||
import dev.inmo.tgbotapi.types.chat.User
|
import dev.inmo.tgbotapi.types.chat.User
|
||||||
import dev.inmo.tgbotapi.types.chat.ChatType
|
import dev.inmo.tgbotapi.types.chat.ChatType
|
||||||
|
import dev.inmo.tgbotapi.types.chat.CommonUser
|
||||||
|
|
||||||
data class BaseInlineQuery(
|
data class BaseInlineQuery(
|
||||||
override val id: InlineQueryIdentifier,
|
override val id: InlineQueryIdentifier,
|
||||||
override val from: User,
|
override val from: CommonUser,
|
||||||
override val query: String,
|
override val query: String,
|
||||||
override val offset: String,
|
override val offset: String,
|
||||||
override val chatType: ChatType?
|
override val chatType: ChatType?
|
||||||
|
|||||||
@@ -3,10 +3,16 @@ package dev.inmo.tgbotapi.types.InlineQueries.query
|
|||||||
import dev.inmo.tgbotapi.abstracts.FromUser
|
import dev.inmo.tgbotapi.abstracts.FromUser
|
||||||
import dev.inmo.tgbotapi.types.InlineQueryIdentifier
|
import dev.inmo.tgbotapi.types.InlineQueryIdentifier
|
||||||
import dev.inmo.tgbotapi.types.chat.ChatType
|
import dev.inmo.tgbotapi.types.chat.ChatType
|
||||||
|
import dev.inmo.tgbotapi.types.chat.CommonUser
|
||||||
|
import dev.inmo.tgbotapi.types.chat.User
|
||||||
|
|
||||||
sealed interface InlineQuery : FromUser {
|
sealed interface InlineQuery : FromUser {
|
||||||
val id: InlineQueryIdentifier
|
val id: InlineQueryIdentifier
|
||||||
val query: String
|
val query: String
|
||||||
val offset: String
|
val offset: String
|
||||||
val chatType: ChatType?
|
val chatType: ChatType?
|
||||||
|
|
||||||
|
override val from: CommonUser
|
||||||
|
override val user: CommonUser
|
||||||
|
get() = from
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,12 @@ package dev.inmo.tgbotapi.types.InlineQueries.query
|
|||||||
import dev.inmo.tgbotapi.types.InlineQueryIdentifier
|
import dev.inmo.tgbotapi.types.InlineQueryIdentifier
|
||||||
import dev.inmo.tgbotapi.types.chat.User
|
import dev.inmo.tgbotapi.types.chat.User
|
||||||
import dev.inmo.tgbotapi.types.chat.ChatType
|
import dev.inmo.tgbotapi.types.chat.ChatType
|
||||||
|
import dev.inmo.tgbotapi.types.chat.CommonUser
|
||||||
import dev.inmo.tgbotapi.types.location.Location
|
import dev.inmo.tgbotapi.types.location.Location
|
||||||
|
|
||||||
data class LocationInlineQuery(
|
data class LocationInlineQuery(
|
||||||
override val id: InlineQueryIdentifier,
|
override val id: InlineQueryIdentifier,
|
||||||
override val from: User,
|
override val from: CommonUser,
|
||||||
override val query: String,
|
override val query: String,
|
||||||
override val offset: String,
|
override val offset: String,
|
||||||
override val chatType: ChatType?,
|
override val chatType: ChatType?,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ internal data class RawInlineQuery(
|
|||||||
@SerialName(idField)
|
@SerialName(idField)
|
||||||
val id: InlineQueryIdentifier,
|
val id: InlineQueryIdentifier,
|
||||||
@SerialName(fromField)
|
@SerialName(fromField)
|
||||||
val from: User,
|
val from: CommonUser,
|
||||||
@SerialName(queryField)
|
@SerialName(queryField)
|
||||||
val query: String,
|
val query: String,
|
||||||
@SerialName(offsetField)
|
@SerialName(offsetField)
|
||||||
|
|||||||
@@ -2,16 +2,20 @@ package dev.inmo.tgbotapi.types.queries.callback
|
|||||||
|
|
||||||
import dev.inmo.tgbotapi.abstracts.FromUser
|
import dev.inmo.tgbotapi.abstracts.FromUser
|
||||||
import dev.inmo.tgbotapi.types.CallbackQueryIdentifier
|
import dev.inmo.tgbotapi.types.CallbackQueryIdentifier
|
||||||
|
import dev.inmo.tgbotapi.types.chat.CommonUser
|
||||||
import dev.inmo.tgbotapi.types.chat.User
|
import dev.inmo.tgbotapi.types.chat.User
|
||||||
|
|
||||||
sealed interface CallbackQuery : FromUser {
|
sealed interface CallbackQuery : FromUser {
|
||||||
val id: CallbackQueryIdentifier
|
val id: CallbackQueryIdentifier
|
||||||
val chatInstance: String
|
val chatInstance: String
|
||||||
|
override val from: CommonUser
|
||||||
|
override val user: CommonUser
|
||||||
|
get() = from
|
||||||
}
|
}
|
||||||
|
|
||||||
data class UnknownCallbackQueryType(
|
data class UnknownCallbackQueryType(
|
||||||
override val id: CallbackQueryIdentifier,
|
override val id: CallbackQueryIdentifier,
|
||||||
override val from: User,
|
override val from: CommonUser,
|
||||||
override val chatInstance: String,
|
override val chatInstance: String,
|
||||||
val raw: String
|
val raw: String
|
||||||
) : CallbackQuery
|
) : CallbackQuery
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
package dev.inmo.tgbotapi.types.queries.callback
|
package dev.inmo.tgbotapi.types.queries.callback
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.types.*
|
import dev.inmo.tgbotapi.types.*
|
||||||
|
import dev.inmo.tgbotapi.types.chat.CommonUser
|
||||||
import dev.inmo.tgbotapi.types.chat.User
|
import dev.inmo.tgbotapi.types.chat.User
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class InlineMessageIdDataCallbackQuery(
|
data class InlineMessageIdDataCallbackQuery(
|
||||||
override val id: CallbackQueryIdentifier,
|
override val id: CallbackQueryIdentifier,
|
||||||
override val from: User,
|
override val from: CommonUser,
|
||||||
override val chatInstance: String,
|
override val chatInstance: String,
|
||||||
override val inlineMessageId: InlineMessageIdentifier,
|
override val inlineMessageId: InlineMessageIdentifier,
|
||||||
override val data: String
|
override val data: String
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
package dev.inmo.tgbotapi.types.queries.callback
|
package dev.inmo.tgbotapi.types.queries.callback
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.types.*
|
import dev.inmo.tgbotapi.types.*
|
||||||
|
import dev.inmo.tgbotapi.types.chat.CommonUser
|
||||||
import dev.inmo.tgbotapi.types.chat.User
|
import dev.inmo.tgbotapi.types.chat.User
|
||||||
|
|
||||||
data class InlineMessageIdGameShortNameCallbackQuery(
|
data class InlineMessageIdGameShortNameCallbackQuery(
|
||||||
override val id: CallbackQueryIdentifier,
|
override val id: CallbackQueryIdentifier,
|
||||||
override val from: User,
|
override val from: CommonUser,
|
||||||
override val chatInstance: String,
|
override val chatInstance: String,
|
||||||
override val inlineMessageId: InlineMessageIdentifier,
|
override val inlineMessageId: InlineMessageIdentifier,
|
||||||
override val gameShortName: String
|
override val gameShortName: String
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
package dev.inmo.tgbotapi.types.queries.callback
|
package dev.inmo.tgbotapi.types.queries.callback
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.types.CallbackQueryIdentifier
|
import dev.inmo.tgbotapi.types.CallbackQueryIdentifier
|
||||||
|
import dev.inmo.tgbotapi.types.chat.CommonUser
|
||||||
import dev.inmo.tgbotapi.types.chat.User
|
import dev.inmo.tgbotapi.types.chat.User
|
||||||
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||||
import dev.inmo.tgbotapi.types.message.content.MessageContent
|
import dev.inmo.tgbotapi.types.message.content.MessageContent
|
||||||
|
|
||||||
data class MessageDataCallbackQuery(
|
data class MessageDataCallbackQuery(
|
||||||
override val id: CallbackQueryIdentifier,
|
override val id: CallbackQueryIdentifier,
|
||||||
override val from: User,
|
override val from: CommonUser,
|
||||||
override val chatInstance: String,
|
override val chatInstance: String,
|
||||||
override val message: ContentMessage<MessageContent>,
|
override val message: ContentMessage<MessageContent>,
|
||||||
override val data: String
|
override val data: String
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
package dev.inmo.tgbotapi.types.queries.callback
|
package dev.inmo.tgbotapi.types.queries.callback
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.types.CallbackQueryIdentifier
|
import dev.inmo.tgbotapi.types.CallbackQueryIdentifier
|
||||||
|
import dev.inmo.tgbotapi.types.chat.CommonUser
|
||||||
import dev.inmo.tgbotapi.types.chat.User
|
import dev.inmo.tgbotapi.types.chat.User
|
||||||
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||||
import dev.inmo.tgbotapi.types.message.content.MessageContent
|
import dev.inmo.tgbotapi.types.message.content.MessageContent
|
||||||
|
|
||||||
data class MessageGameShortNameCallbackQuery(
|
data class MessageGameShortNameCallbackQuery(
|
||||||
override val id: CallbackQueryIdentifier,
|
override val id: CallbackQueryIdentifier,
|
||||||
override val from: User,
|
override val from: CommonUser,
|
||||||
override val chatInstance: String,
|
override val chatInstance: String,
|
||||||
override val message: ContentMessage<MessageContent>,
|
override val message: ContentMessage<MessageContent>,
|
||||||
override val gameShortName: String
|
override val gameShortName: String
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package dev.inmo.tgbotapi.types.queries.callback
|
package dev.inmo.tgbotapi.types.queries.callback
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.types.*
|
import dev.inmo.tgbotapi.types.*
|
||||||
|
import dev.inmo.tgbotapi.types.chat.CommonUser
|
||||||
import dev.inmo.tgbotapi.types.chat.User
|
import dev.inmo.tgbotapi.types.chat.User
|
||||||
import dev.inmo.tgbotapi.types.message.abstracts.*
|
import dev.inmo.tgbotapi.types.message.abstracts.*
|
||||||
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializeOnlySerializer
|
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializeOnlySerializer
|
||||||
@@ -13,7 +14,7 @@ internal data class RawCallbackQuery(
|
|||||||
@SerialName(idField)
|
@SerialName(idField)
|
||||||
val id: CallbackQueryIdentifier,
|
val id: CallbackQueryIdentifier,
|
||||||
@SerialName(fromField)
|
@SerialName(fromField)
|
||||||
val from: User,
|
val from: CommonUser,
|
||||||
@Serializable(TelegramBotAPIMessageDeserializeOnlySerializer::class)
|
@Serializable(TelegramBotAPIMessageDeserializeOnlySerializer::class)
|
||||||
val message: ContentMessage<MessageContent>? = null,
|
val message: ContentMessage<MessageContent>? = null,
|
||||||
@SerialName(inlineMessageIdField)
|
@SerialName(inlineMessageIdField)
|
||||||
|
|||||||
@@ -18,10 +18,16 @@ fun makeChatLink(identifier: Identifier, threadId: MessageThreadId? = null) = id
|
|||||||
fun makeUsernameDeepLinkPrefix(username: String) = "${makeUsernameLink(username)}?start="
|
fun makeUsernameDeepLinkPrefix(username: String) = "${makeUsernameLink(username)}?start="
|
||||||
fun makeUsernameStartattachPrefix(username: String) = "$internalLinkBeginning/$username?startattach"
|
fun makeUsernameStartattachPrefix(username: String) = "$internalLinkBeginning/$username?startattach"
|
||||||
fun makeUsernameStartattachLink(username: String, data: String? = null) = "${makeUsernameStartattachPrefix(username)}${data?.let { "=$it" } ?: ""}"
|
fun makeUsernameStartattachLink(username: String, data: String? = null) = "${makeUsernameStartattachPrefix(username)}${data?.let { "=$it" } ?: ""}"
|
||||||
inline val Username.link
|
inline val Username.usernameLink
|
||||||
get() = makeUsernameLink(usernameWithoutAt)
|
get() = makeUsernameLink(usernameWithoutAt)
|
||||||
val IdChatIdentifier.link: String
|
@Deprecated("Deprecated due to the conflicts in name", ReplaceWith("this.usernameLink", "dev.inmo.tgbotapi.extensions.utils.formatting.usernameLink"))
|
||||||
|
inline val Username.link
|
||||||
|
get() = usernameLink
|
||||||
|
val IdChatIdentifier.chatLink: String
|
||||||
get() = makeChatLink(chatId, threadId)
|
get() = makeChatLink(chatId, threadId)
|
||||||
|
@Deprecated("Deprecated due to the conflicts in name", ReplaceWith("this.chatLink", "dev.inmo.tgbotapi.extensions.utils.formatting.chatLink"))
|
||||||
|
val IdChatIdentifier.link: String
|
||||||
|
get() = chatLink
|
||||||
fun ChatId.link(threadId: MessageThreadId?) = makeChatLink(chatId, threadId)
|
fun ChatId.link(threadId: MessageThreadId?) = makeChatLink(chatId, threadId)
|
||||||
inline fun Username.link(threadId: MessageThreadId?) = makeUsernameLink(usernameWithoutAt, threadId)
|
inline fun Username.link(threadId: MessageThreadId?) = makeUsernameLink(usernameWithoutAt, threadId)
|
||||||
inline val Username.deepLinkPrefix
|
inline val Username.deepLinkPrefix
|
||||||
@@ -83,20 +89,27 @@ fun makeLinkToMessage(
|
|||||||
/**
|
/**
|
||||||
* @see makeLinkToMessage
|
* @see makeLinkToMessage
|
||||||
*/
|
*/
|
||||||
val Message.link: String?
|
val Message.messageLink: String?
|
||||||
get() = makeLinkToMessage(
|
get() = makeLinkToMessage(
|
||||||
chat,
|
chat,
|
||||||
messageId
|
messageId
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see makeLinkToMessage
|
||||||
|
*/
|
||||||
|
@Deprecated("Deprecated due to the conflicts in name", ReplaceWith("this.messageLink", "dev.inmo.tgbotapi.extensions.utils.formatting.messageLink"))
|
||||||
|
val Message.link: String?
|
||||||
|
get() = messageLink
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Link which can be used as by any user to get access to [Chat]. Returns null in case when there are no
|
* Link which can be used as by any user to get access to [Chat]. Returns null in case when there are no
|
||||||
* known way to build link
|
* known way to build link
|
||||||
*/
|
*/
|
||||||
val Chat.link: String?
|
val Chat.chatLink: String?
|
||||||
get() {
|
get() {
|
||||||
if (this is UsernameChat) {
|
if (this is UsernameChat) {
|
||||||
username ?.link ?: id.link
|
username ?.usernameLink ?: id.chatLink
|
||||||
}
|
}
|
||||||
if (this is ExtendedPublicChat) {
|
if (this is ExtendedPublicChat) {
|
||||||
inviteLink ?.let { return it }
|
inviteLink ?.let { return it }
|
||||||
@@ -107,6 +120,14 @@ val Chat.link: String?
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link which can be used as by any user to get access to [Chat]. Returns null in case when there are no
|
||||||
|
* known way to build link
|
||||||
|
*/
|
||||||
|
@Deprecated("Deprecated due to the conflicts in name", ReplaceWith("this.chatLink", "dev.inmo.tgbotapi.extensions.utils.formatting.chatLink"))
|
||||||
|
val Chat.link: String?
|
||||||
|
get() = chatLink
|
||||||
|
|
||||||
private const val stickerSetAddingLinkPrefix = "$internalLinkBeginning/addstickers"
|
private const val stickerSetAddingLinkPrefix = "$internalLinkBeginning/addstickers"
|
||||||
|
|
||||||
val StickerSetName.stickerSetLink
|
val StickerSetName.stickerSetLink
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ fun List<Update>.lastUpdateIdentifier(): UpdateIdentifier? {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will convert incoming list of updates to list with [MediaGroupUpdate]s
|
* Will convert incoming list of [Update]s to list with [Update]s, which include [dev.inmo.tgbotapi.types.message.abstracts.ContentMessage]s
|
||||||
|
* with [dev.inmo.tgbotapi.types.message.content.MediaGroupContent]
|
||||||
*/
|
*/
|
||||||
fun List<Update>.convertWithMediaGroupUpdates(): List<Update> {
|
fun List<Update>.convertWithMediaGroupUpdates(): List<Update> {
|
||||||
val resultUpdates = mutableListOf<Update>()
|
val resultUpdates = mutableListOf<Update>()
|
||||||
@@ -67,4 +68,5 @@ fun List<Update>.convertWithMediaGroupUpdates(): List<Update> {
|
|||||||
*
|
*
|
||||||
* @throws IllegalStateException
|
* @throws IllegalStateException
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("Redundant", ReplaceWith("this"))
|
||||||
fun BaseEditMessageUpdate.toEditMediaGroupUpdate() = this
|
fun BaseEditMessageUpdate.toEditMediaGroupUpdate() = this
|
||||||
|
|||||||
@@ -19,12 +19,18 @@ import io.ktor.utils.io.CancellationException
|
|||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
|
||||||
|
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
|
||||||
|
* retrieved in different updates
|
||||||
|
*/
|
||||||
fun TelegramBot.longPollingFlow(
|
fun TelegramBot.longPollingFlow(
|
||||||
timeoutSeconds: Seconds = 30,
|
timeoutSeconds: Seconds = 30,
|
||||||
exceptionsHandler: (ExceptionHandler<Unit>)? = null,
|
exceptionsHandler: (ExceptionHandler<Unit>)? = null,
|
||||||
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
|
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
|
||||||
autoDisableWebhooks: Boolean = true,
|
autoDisableWebhooks: Boolean = true,
|
||||||
autoSkipTimeoutExceptions: Boolean = true
|
autoSkipTimeoutExceptions: Boolean = true,
|
||||||
|
mediaGroupsDebounceTimeMillis: Long? = 1000L,
|
||||||
): Flow<Update> = channelFlow {
|
): Flow<Update> = channelFlow {
|
||||||
if (autoDisableWebhooks) {
|
if (autoDisableWebhooks) {
|
||||||
runCatchingSafely {
|
runCatchingSafely {
|
||||||
@@ -47,6 +53,52 @@ fun TelegramBot.longPollingFlow(
|
|||||||
|
|
||||||
var lastUpdateIdentifier: UpdateIdentifier? = null
|
var lastUpdateIdentifier: UpdateIdentifier? = null
|
||||||
|
|
||||||
|
val updatesHandler: (suspend (List<Update>) -> Unit) = if (mediaGroupsDebounceTimeMillis != null) {
|
||||||
|
val scope = CoroutineScope(contextToWork)
|
||||||
|
val updatesReceiver = scope.updateHandlerWithMediaGroupsAdaptation(
|
||||||
|
{
|
||||||
|
withContext(contextToWork) {
|
||||||
|
send(it)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mediaGroupsDebounceTimeMillis
|
||||||
|
);
|
||||||
|
{ originalUpdates: List<Update> ->
|
||||||
|
originalUpdates.forEach {
|
||||||
|
updatesReceiver(it)
|
||||||
|
lastUpdateIdentifier = maxOf(lastUpdateIdentifier ?: it.updateId, it.updateId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
{ originalUpdates: List<Update> ->
|
||||||
|
val converted = originalUpdates.convertWithMediaGroupUpdates()
|
||||||
|
/**
|
||||||
|
* Dirty hack for cases when the media group was retrieved not fully:
|
||||||
|
*
|
||||||
|
* We are throw out the last media group and will reretrieve it again in the next get updates
|
||||||
|
* and it will guarantee that it is full
|
||||||
|
*/
|
||||||
|
val updates = if (
|
||||||
|
originalUpdates.size == getUpdatesLimit.last
|
||||||
|
&& ((converted.last() as? BaseSentMessageUpdate) ?.data as? CommonMessage<*>) ?.content is MediaGroupContent<*>
|
||||||
|
) {
|
||||||
|
converted - converted.last()
|
||||||
|
} else {
|
||||||
|
converted
|
||||||
|
}
|
||||||
|
|
||||||
|
safelyWithResult {
|
||||||
|
for (update in updates) {
|
||||||
|
send(update)
|
||||||
|
|
||||||
|
lastUpdateIdentifier = update.updateId
|
||||||
|
}
|
||||||
|
}.onFailure {
|
||||||
|
cancel(it as? CancellationException ?: return@onFailure)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
withContext(contextToWork) {
|
withContext(contextToWork) {
|
||||||
while (isActive) {
|
while (isActive) {
|
||||||
safely(
|
safely(
|
||||||
@@ -64,50 +116,25 @@ fun TelegramBot.longPollingFlow(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
val updates = execute(
|
execute(
|
||||||
GetUpdates(
|
GetUpdates(
|
||||||
offset = lastUpdateIdentifier?.plus(1),
|
offset = lastUpdateIdentifier?.plus(1),
|
||||||
timeout = timeoutSeconds,
|
timeout = timeoutSeconds,
|
||||||
allowed_updates = allowedUpdates
|
allowed_updates = allowedUpdates
|
||||||
)
|
)
|
||||||
).let { originalUpdates ->
|
).let { originalUpdates ->
|
||||||
val converted = originalUpdates.convertWithMediaGroupUpdates()
|
updatesHandler(originalUpdates)
|
||||||
/**
|
|
||||||
* Dirty hack for cases when the media group was retrieved not fully:
|
|
||||||
*
|
|
||||||
* We are throw out the last media group and will reretrieve it again in the next get updates
|
|
||||||
* and it will guarantee that it is full
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Dirty hack for cases when the media group was retrieved not fully:
|
|
||||||
*
|
|
||||||
* We are throw out the last media group and will reretrieve it again in the next get updates
|
|
||||||
* and it will guarantee that it is full
|
|
||||||
*/
|
|
||||||
if (
|
|
||||||
originalUpdates.size == getUpdatesLimit.last
|
|
||||||
&& ((converted.last() as? BaseSentMessageUpdate) ?.data as? CommonMessage<*>) ?.content is MediaGroupContent<*>
|
|
||||||
) {
|
|
||||||
converted - converted.last()
|
|
||||||
} else {
|
|
||||||
converted
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
safelyWithResult {
|
|
||||||
for (update in updates) {
|
|
||||||
send(update)
|
|
||||||
|
|
||||||
lastUpdateIdentifier = update.updateId
|
|
||||||
}
|
|
||||||
}.onFailure {
|
|
||||||
cancel(it as? CancellationException ?: return@onFailure)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
|
||||||
|
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
|
||||||
|
* retrieved in different updates
|
||||||
|
*/
|
||||||
fun TelegramBot.startGettingOfUpdatesByLongPolling(
|
fun TelegramBot.startGettingOfUpdatesByLongPolling(
|
||||||
timeoutSeconds: Seconds = 30,
|
timeoutSeconds: Seconds = 30,
|
||||||
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
||||||
@@ -115,13 +142,15 @@ fun TelegramBot.startGettingOfUpdatesByLongPolling(
|
|||||||
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
|
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
|
||||||
autoDisableWebhooks: Boolean = true,
|
autoDisableWebhooks: Boolean = true,
|
||||||
autoSkipTimeoutExceptions: Boolean = true,
|
autoSkipTimeoutExceptions: Boolean = true,
|
||||||
|
mediaGroupsDebounceTimeMillis: Long? = 1000L,
|
||||||
updatesReceiver: UpdateReceiver<Update>
|
updatesReceiver: UpdateReceiver<Update>
|
||||||
): Job = longPollingFlow(
|
): Job = longPollingFlow(
|
||||||
timeoutSeconds = timeoutSeconds,
|
timeoutSeconds = timeoutSeconds,
|
||||||
exceptionsHandler = exceptionsHandler,
|
exceptionsHandler = exceptionsHandler,
|
||||||
allowedUpdates = allowedUpdates,
|
allowedUpdates = allowedUpdates,
|
||||||
autoDisableWebhooks = autoDisableWebhooks,
|
autoDisableWebhooks = autoDisableWebhooks,
|
||||||
autoSkipTimeoutExceptions = autoSkipTimeoutExceptions
|
autoSkipTimeoutExceptions = autoSkipTimeoutExceptions,
|
||||||
|
mediaGroupsDebounceTimeMillis = mediaGroupsDebounceTimeMillis
|
||||||
).subscribeSafely(
|
).subscribeSafely(
|
||||||
scope,
|
scope,
|
||||||
exceptionsHandler ?: defaultSafelyExceptionHandler,
|
exceptionsHandler ?: defaultSafelyExceptionHandler,
|
||||||
@@ -129,6 +158,10 @@ fun TelegramBot.startGettingOfUpdatesByLongPolling(
|
|||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
|
||||||
|
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
|
||||||
|
* retrieved in different updates
|
||||||
|
*
|
||||||
* @return [kotlinx.coroutines.flow.Flow] which will emit updates to the collector while they will be accumulated. Works
|
* @return [kotlinx.coroutines.flow.Flow] which will emit updates to the collector while they will be accumulated. Works
|
||||||
* the same as [longPollingFlow], but it will cancel the flow after the first one [HttpRequestTimeoutException]
|
* the same as [longPollingFlow], but it will cancel the flow after the first one [HttpRequestTimeoutException]
|
||||||
*/
|
*/
|
||||||
@@ -137,7 +170,8 @@ fun TelegramBot.createAccumulatedUpdatesRetrieverFlow(
|
|||||||
avoidCallbackQueries: Boolean = false,
|
avoidCallbackQueries: Boolean = false,
|
||||||
exceptionsHandler: ExceptionHandler<Unit>? = null,
|
exceptionsHandler: ExceptionHandler<Unit>? = null,
|
||||||
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
|
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
|
||||||
autoDisableWebhooks: Boolean = true
|
autoDisableWebhooks: Boolean = true,
|
||||||
|
mediaGroupsDebounceTimeMillis: Long? = 1000L,
|
||||||
): Flow<Update> = longPollingFlow(
|
): Flow<Update> = longPollingFlow(
|
||||||
timeoutSeconds = 0,
|
timeoutSeconds = 0,
|
||||||
exceptionsHandler = {
|
exceptionsHandler = {
|
||||||
@@ -149,11 +183,17 @@ fun TelegramBot.createAccumulatedUpdatesRetrieverFlow(
|
|||||||
},
|
},
|
||||||
allowedUpdates = allowedUpdates,
|
allowedUpdates = allowedUpdates,
|
||||||
autoDisableWebhooks = autoDisableWebhooks,
|
autoDisableWebhooks = autoDisableWebhooks,
|
||||||
autoSkipTimeoutExceptions = false
|
autoSkipTimeoutExceptions = false,
|
||||||
|
mediaGroupsDebounceTimeMillis = mediaGroupsDebounceTimeMillis
|
||||||
).filter {
|
).filter {
|
||||||
!(it is InlineQueryUpdate && avoidInlineQueries || it is CallbackQueryUpdate && avoidCallbackQueries)
|
!(it is InlineQueryUpdate && avoidInlineQueries || it is CallbackQueryUpdate && avoidCallbackQueries)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
|
||||||
|
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
|
||||||
|
* retrieved in different updates
|
||||||
|
*/
|
||||||
fun TelegramBot.retrieveAccumulatedUpdates(
|
fun TelegramBot.retrieveAccumulatedUpdates(
|
||||||
avoidInlineQueries: Boolean = false,
|
avoidInlineQueries: Boolean = false,
|
||||||
avoidCallbackQueries: Boolean = false,
|
avoidCallbackQueries: Boolean = false,
|
||||||
@@ -161,25 +201,33 @@ fun TelegramBot.retrieveAccumulatedUpdates(
|
|||||||
exceptionsHandler: (ExceptionHandler<Unit>)? = null,
|
exceptionsHandler: (ExceptionHandler<Unit>)? = null,
|
||||||
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
|
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
|
||||||
autoDisableWebhooks: Boolean = true,
|
autoDisableWebhooks: Boolean = true,
|
||||||
|
mediaGroupsDebounceTimeMillis: Long? = 1000L,
|
||||||
updatesReceiver: UpdateReceiver<Update>
|
updatesReceiver: UpdateReceiver<Update>
|
||||||
): Job = createAccumulatedUpdatesRetrieverFlow(
|
): Job = createAccumulatedUpdatesRetrieverFlow(
|
||||||
avoidInlineQueries,
|
avoidInlineQueries,
|
||||||
avoidCallbackQueries,
|
avoidCallbackQueries,
|
||||||
exceptionsHandler,
|
exceptionsHandler,
|
||||||
allowedUpdates,
|
allowedUpdates,
|
||||||
autoDisableWebhooks
|
autoDisableWebhooks,
|
||||||
|
mediaGroupsDebounceTimeMillis
|
||||||
).subscribeSafelyWithoutExceptions(
|
).subscribeSafelyWithoutExceptions(
|
||||||
scope.LinkedSupervisorScope()
|
scope.LinkedSupervisorScope()
|
||||||
) {
|
) {
|
||||||
updatesReceiver(it)
|
updatesReceiver(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
|
||||||
|
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
|
||||||
|
* retrieved in different updates
|
||||||
|
*/
|
||||||
fun TelegramBot.retrieveAccumulatedUpdates(
|
fun TelegramBot.retrieveAccumulatedUpdates(
|
||||||
flowsUpdatesFilter: FlowsUpdatesFilter,
|
flowsUpdatesFilter: FlowsUpdatesFilter,
|
||||||
avoidInlineQueries: Boolean = false,
|
avoidInlineQueries: Boolean = false,
|
||||||
avoidCallbackQueries: Boolean = false,
|
avoidCallbackQueries: Boolean = false,
|
||||||
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
||||||
autoDisableWebhooks: Boolean = true,
|
autoDisableWebhooks: Boolean = true,
|
||||||
|
mediaGroupsDebounceTimeMillis: Long? = 1000L,
|
||||||
exceptionsHandler: ExceptionHandler<Unit>? = null
|
exceptionsHandler: ExceptionHandler<Unit>? = null
|
||||||
) = retrieveAccumulatedUpdates(
|
) = retrieveAccumulatedUpdates(
|
||||||
avoidInlineQueries,
|
avoidInlineQueries,
|
||||||
@@ -188,9 +236,15 @@ fun TelegramBot.retrieveAccumulatedUpdates(
|
|||||||
exceptionsHandler,
|
exceptionsHandler,
|
||||||
flowsUpdatesFilter.allowedUpdates,
|
flowsUpdatesFilter.allowedUpdates,
|
||||||
autoDisableWebhooks,
|
autoDisableWebhooks,
|
||||||
|
mediaGroupsDebounceTimeMillis,
|
||||||
flowsUpdatesFilter.asUpdateReceiver
|
flowsUpdatesFilter.asUpdateReceiver
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
|
||||||
|
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
|
||||||
|
* retrieved in different updates
|
||||||
|
*/
|
||||||
suspend fun TelegramBot.flushAccumulatedUpdates(
|
suspend fun TelegramBot.flushAccumulatedUpdates(
|
||||||
avoidInlineQueries: Boolean = false,
|
avoidInlineQueries: Boolean = false,
|
||||||
avoidCallbackQueries: Boolean = false,
|
avoidCallbackQueries: Boolean = false,
|
||||||
@@ -198,6 +252,7 @@ suspend fun TelegramBot.flushAccumulatedUpdates(
|
|||||||
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
|
allowedUpdates: List<String>? = ALL_UPDATES_LIST,
|
||||||
exceptionsHandler: ExceptionHandler<Unit>? = null,
|
exceptionsHandler: ExceptionHandler<Unit>? = null,
|
||||||
autoDisableWebhooks: Boolean = true,
|
autoDisableWebhooks: Boolean = true,
|
||||||
|
mediaGroupsDebounceTimeMillis: Long? = 1000L,
|
||||||
updatesReceiver: UpdateReceiver<Update> = {}
|
updatesReceiver: UpdateReceiver<Update> = {}
|
||||||
) = retrieveAccumulatedUpdates(
|
) = retrieveAccumulatedUpdates(
|
||||||
avoidInlineQueries,
|
avoidInlineQueries,
|
||||||
@@ -206,12 +261,17 @@ suspend fun TelegramBot.flushAccumulatedUpdates(
|
|||||||
exceptionsHandler,
|
exceptionsHandler,
|
||||||
allowedUpdates,
|
allowedUpdates,
|
||||||
autoDisableWebhooks,
|
autoDisableWebhooks,
|
||||||
|
mediaGroupsDebounceTimeMillis,
|
||||||
updatesReceiver
|
updatesReceiver
|
||||||
).join()
|
).join()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will [startGettingOfUpdatesByLongPolling] using incoming [flowsUpdatesFilter]. It is assumed that you ALREADY CONFIGURE
|
* Will [startGettingOfUpdatesByLongPolling] using incoming [updatesFilter]. It is assumed that you ALREADY CONFIGURE
|
||||||
* all updates receivers, because this method will trigger getting of updates and.
|
* all updates receivers, because this method will trigger getting of updates and.
|
||||||
|
*
|
||||||
|
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
|
||||||
|
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
|
||||||
|
* retrieved in different updates
|
||||||
*/
|
*/
|
||||||
fun TelegramBot.longPolling(
|
fun TelegramBot.longPolling(
|
||||||
updatesFilter: UpdatesFilter,
|
updatesFilter: UpdatesFilter,
|
||||||
@@ -219,6 +279,7 @@ fun TelegramBot.longPolling(
|
|||||||
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
||||||
autoDisableWebhooks: Boolean = true,
|
autoDisableWebhooks: Boolean = true,
|
||||||
autoSkipTimeoutExceptions: Boolean = true,
|
autoSkipTimeoutExceptions: Boolean = true,
|
||||||
|
mediaGroupsDebounceTimeMillis: Long? = 1000L,
|
||||||
exceptionsHandler: ExceptionHandler<Unit>? = null
|
exceptionsHandler: ExceptionHandler<Unit>? = null
|
||||||
): Job = updatesFilter.run {
|
): Job = updatesFilter.run {
|
||||||
startGettingOfUpdatesByLongPolling(
|
startGettingOfUpdatesByLongPolling(
|
||||||
@@ -228,6 +289,7 @@ fun TelegramBot.longPolling(
|
|||||||
allowedUpdates = allowedUpdates,
|
allowedUpdates = allowedUpdates,
|
||||||
autoDisableWebhooks = autoDisableWebhooks,
|
autoDisableWebhooks = autoDisableWebhooks,
|
||||||
autoSkipTimeoutExceptions = autoSkipTimeoutExceptions,
|
autoSkipTimeoutExceptions = autoSkipTimeoutExceptions,
|
||||||
|
mediaGroupsDebounceTimeMillis = mediaGroupsDebounceTimeMillis,
|
||||||
updatesReceiver = asUpdateReceiver
|
updatesReceiver = asUpdateReceiver
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -236,6 +298,10 @@ fun TelegramBot.longPolling(
|
|||||||
* Will enable [longPolling] by creating [FlowsUpdatesFilter] with [flowsUpdatesFilterUpdatesKeeperCount] as an argument
|
* Will enable [longPolling] by creating [FlowsUpdatesFilter] with [flowsUpdatesFilterUpdatesKeeperCount] as an argument
|
||||||
* and applied [flowUpdatesPreset]. It is assumed that you WILL CONFIGURE all updates receivers in [flowUpdatesPreset],
|
* and applied [flowUpdatesPreset]. It is assumed that you WILL CONFIGURE all updates receivers in [flowUpdatesPreset],
|
||||||
* because of after [flowUpdatesPreset] method calling will be triggered getting of updates.
|
* because of after [flowUpdatesPreset] method calling will be triggered getting of updates.
|
||||||
|
*
|
||||||
|
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
|
||||||
|
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
|
||||||
|
* retrieved in different updates
|
||||||
*/
|
*/
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
fun TelegramBot.longPolling(
|
fun TelegramBot.longPolling(
|
||||||
@@ -245,15 +311,22 @@ fun TelegramBot.longPolling(
|
|||||||
flowsUpdatesFilterUpdatesKeeperCount: Int = 100,
|
flowsUpdatesFilterUpdatesKeeperCount: Int = 100,
|
||||||
autoDisableWebhooks: Boolean = true,
|
autoDisableWebhooks: Boolean = true,
|
||||||
autoSkipTimeoutExceptions: Boolean = true,
|
autoSkipTimeoutExceptions: Boolean = true,
|
||||||
|
mediaGroupsDebounceTimeMillis: Long? = 1000L,
|
||||||
flowUpdatesPreset: FlowsUpdatesFilter.() -> Unit
|
flowUpdatesPreset: FlowsUpdatesFilter.() -> Unit
|
||||||
): Job = longPolling(FlowsUpdatesFilter(flowsUpdatesFilterUpdatesKeeperCount).apply(flowUpdatesPreset), timeoutSeconds, scope, autoDisableWebhooks, autoSkipTimeoutExceptions, exceptionsHandler)
|
): Job = longPolling(FlowsUpdatesFilter(flowsUpdatesFilterUpdatesKeeperCount).apply(flowUpdatesPreset), timeoutSeconds, scope, autoDisableWebhooks, autoSkipTimeoutExceptions, mediaGroupsDebounceTimeMillis, exceptionsHandler)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
|
||||||
|
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
|
||||||
|
* retrieved in different updates
|
||||||
|
*/
|
||||||
fun RequestsExecutor.startGettingOfUpdatesByLongPolling(
|
fun RequestsExecutor.startGettingOfUpdatesByLongPolling(
|
||||||
updatesFilter: UpdatesFilter,
|
updatesFilter: UpdatesFilter,
|
||||||
timeoutSeconds: Seconds = 30,
|
timeoutSeconds: Seconds = 30,
|
||||||
exceptionsHandler: ExceptionHandler<Unit>? = null,
|
exceptionsHandler: ExceptionHandler<Unit>? = null,
|
||||||
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
||||||
autoDisableWebhooks: Boolean = true,
|
autoDisableWebhooks: Boolean = true,
|
||||||
|
mediaGroupsDebounceTimeMillis: Long? = 1000L,
|
||||||
autoSkipTimeoutExceptions: Boolean = true,
|
autoSkipTimeoutExceptions: Boolean = true,
|
||||||
): Job = startGettingOfUpdatesByLongPolling(
|
): Job = startGettingOfUpdatesByLongPolling(
|
||||||
timeoutSeconds,
|
timeoutSeconds,
|
||||||
@@ -262,5 +335,6 @@ fun RequestsExecutor.startGettingOfUpdatesByLongPolling(
|
|||||||
updatesFilter.allowedUpdates,
|
updatesFilter.allowedUpdates,
|
||||||
autoDisableWebhooks,
|
autoDisableWebhooks,
|
||||||
autoSkipTimeoutExceptions,
|
autoSkipTimeoutExceptions,
|
||||||
|
mediaGroupsDebounceTimeMillis,
|
||||||
updatesFilter.asUpdateReceiver
|
updatesFilter.asUpdateReceiver
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package dev.inmo.tgbotapi.extensions.utils.updates.retrieving
|
package dev.inmo.tgbotapi.extensions.utils.updates.retrieving
|
||||||
|
|
||||||
import dev.inmo.micro_utils.coroutines.launchSafely
|
|
||||||
import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions
|
import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions
|
||||||
import dev.inmo.tgbotapi.extensions.utils.updates.convertWithMediaGroupUpdates
|
import dev.inmo.tgbotapi.extensions.utils.updates.convertWithMediaGroupUpdates
|
||||||
import dev.inmo.tgbotapi.types.message.abstracts.PossiblyMediaGroupMessage
|
import dev.inmo.tgbotapi.types.message.abstracts.PossiblyMediaGroupMessage
|
||||||
@@ -12,7 +11,6 @@ import kotlinx.coroutines.CoroutineScope
|
|||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create [UpdateReceiver] object which will correctly accumulate updates and send into output updates which INCLUDE
|
* Create [UpdateReceiver] object which will correctly accumulate updates and send into output updates which INCLUDE
|
||||||
* [dev.inmo.tgbotapi.types.update.MediaGroupUpdates.MediaGroupUpdate]s.
|
* [dev.inmo.tgbotapi.types.update.MediaGroupUpdates.MediaGroupUpdate]s.
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ import java.util.concurrent.Executors
|
|||||||
* @param [scope] Will be used for mapping of media groups
|
* @param [scope] Will be used for mapping of media groups
|
||||||
* @param [exceptionsHandler] Pass this parameter to set custom exception handler for getting updates
|
* @param [exceptionsHandler] Pass this parameter to set custom exception handler for getting updates
|
||||||
* @param [block] Some receiver block like [dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter]
|
* @param [block] Some receiver block like [dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter]
|
||||||
|
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
|
||||||
|
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
|
||||||
|
* retrieved in different updates
|
||||||
*
|
*
|
||||||
* @see dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
|
* @see dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
|
||||||
* @see UpdatesFilter
|
* @see UpdatesFilter
|
||||||
@@ -57,6 +60,11 @@ fun Route.includeWebhookHandlingInRoute(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
|
||||||
|
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
|
||||||
|
* retrieved in different updates
|
||||||
|
*/
|
||||||
fun Route.includeWebhookHandlingInRouteWithFlows(
|
fun Route.includeWebhookHandlingInRouteWithFlows(
|
||||||
scope: CoroutineScope,
|
scope: CoroutineScope,
|
||||||
exceptionsHandler: ExceptionHandler<Unit>? = null,
|
exceptionsHandler: ExceptionHandler<Unit>? = null,
|
||||||
@@ -76,6 +84,9 @@ fun Route.includeWebhookHandlingInRouteWithFlows(
|
|||||||
* @param listenRoute address to listen by bot. If null - will be set up in root of host
|
* @param listenRoute address to listen by bot. If null - will be set up in root of host
|
||||||
* @param scope Scope which will be used for
|
* @param scope Scope which will be used for
|
||||||
* @param privateKeyConfig If configured - server will be created with [sslConnector]. [connector] will be used otherwise
|
* @param privateKeyConfig If configured - server will be created with [sslConnector]. [connector] will be used otherwise
|
||||||
|
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
|
||||||
|
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
|
||||||
|
* retrieved in different updates
|
||||||
*
|
*
|
||||||
* @see dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
|
* @see dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
|
||||||
* @see UpdatesFilter
|
* @see UpdatesFilter
|
||||||
@@ -132,6 +143,9 @@ fun startListenWebhooks(
|
|||||||
* @param listenPort port which will be listen by bot
|
* @param listenPort port which will be listen by bot
|
||||||
* @param listenRoute address to listen by bot
|
* @param listenRoute address to listen by bot
|
||||||
* @param scope Scope which will be used for
|
* @param scope Scope which will be used for
|
||||||
|
* @param mediaGroupsDebounceTimeMillis Will be used for calling of [updateHandlerWithMediaGroupsAdaptation]. Pass null
|
||||||
|
* in case you wish to enable classic way of updates handling, but in that mode some media group messages can be
|
||||||
|
* retrieved in different updates
|
||||||
*
|
*
|
||||||
* @see dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
|
* @see dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
|
||||||
* @see UpdatesFilter
|
* @see UpdatesFilter
|
||||||
|
|||||||
Reference in New Issue
Block a user