1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2025-12-02 20:35:43 +00:00

Compare commits

..

25 Commits

Author SHA1 Message Date
841ae73f7c replyWithDice 2021-02-17 17:10:21 +06:00
41b4d29917 updates in slot machine utils 2021-02-17 16:58:57 +06:00
f8b3c44146 update micro_utils 2021-02-16 13:48:32 +06:00
f0eb670c3f start 0.32.6 2021-02-16 13:47:31 +06:00
fe5d94f31e Update README.md 2021-02-13 10:09:33 +06:00
7901d0a223 Update README.md 2021-02-13 01:42:35 +06:00
799f9123ba Update README.md 2021-02-13 01:38:31 +06:00
f77f010e66 Update README.md 2021-02-11 13:38:55 +06:00
67ddf8d809 Update README.md 2021-02-11 13:37:24 +06:00
81afa46253 Update README.md 2021-02-11 13:36:53 +06:00
a5bba76f07 Update README.md 2021-02-11 13:35:06 +06:00
d882cf9c97 update readme 2021-02-11 12:06:34 +06:00
2e27b8b64d Merge pull request #295 from InsanusMokrassar/0.32.5
0.32.5
2021-02-09 19:13:42 +06:00
4df800eaa9 fix of #291 2021-02-09 19:07:31 +06:00
8d27349868 update content resends and different other things 2021-02-09 18:26:10 +06:00
2a89c41a58 fix of #292 2021-02-09 17:15:28 +06:00
098b5cc393 rewrite createAccumulatedUpdatesRetrieverFlow onto channelFlow 2021-02-09 16:33:48 +06:00
10f4817283 solution of #293 2021-02-08 19:35:32 +06:00
4449893608 fix of #294 2021-02-08 18:15:54 +06:00
3a53f41f66 start 0.32.5 2021-02-08 11:36:20 +06:00
7cd366d893 Update README.md 2021-02-07 18:02:20 +06:00
1309a4111c Merge pull request #290 from InsanusMokrassar/0.32.4
content messages renames
2021-02-07 16:59:51 +06:00
eca0680f2f update readme 2021-02-07 12:44:38 +06:00
d472d371ed Merge pull request #282 from InsanusMokrassar/0.32.4
0.32.4
2021-02-07 12:43:08 +06:00
ff16f9a315 Update README.md 2021-02-05 01:18:38 +06:00
27 changed files with 381 additions and 338 deletions

View File

@@ -1,5 +1,28 @@
# TelegramBotAPI changelog
## 0.32.6
* `Common`:
* `Version`:
* `MicroUtils`: `0.4.24` -> `0.4.25`
* `Extensions API`:
* New extension `TelegramBot#replyWithDice`
* `Extensions Utils`:
* `SlotMachineReelImages` has been renamed to `SlotMachineReelImage`
* `SlotMachineReelImage` got two built-in parameters: `text` and `number`
* New extension `String#asSlotMachineReelImage`
## 0.32.5
* `Core`:
* Add `mention` variants for user ids and receiver variants ([#294](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/294))
* Now `AbstractRequestCallFactory` will set up one-second delay for zero timeouts in `GetUpdate` requests
* Several extensions for `TelegramBotAPI` like `retrieveAccumulatedUpdates` have been added as a solution for
[#293](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/293)
* Links for `tg://user?id=<user_id>` have been updated ([#292](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/292))
* All usages of captions or texts in resends and same things have been replaced with `textSources`
* Global `defaultParseMode` has been added ([#291](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/291))
## 0.32.4
* `Common`:

223
README.md
View File

@@ -1,153 +1,118 @@
[Participate in our common survey ☺](https://forms.gle/q6Xf8K3fD1pPsYUw9)
# TelegramBotAPI
<details>
<summary><b>I do not wanna read a lot, just give me my bot</b></summary>
Hello! This is a set of libraries for working with Telegram Bot API.
You can simply use <a href="https://github.com/InsanusMokrassar/TelegramBotAPI-bot_template">this template</a> (and button
<a href="https://github.com/InsanusMokrassar/TelegramBotAPI-bot_template/generate">Use template</a>) to get your copy of bot and start to code.
<p></p>
<b>P.S. Do not forget to look into our <a href="https://bookstack.inmo.dev/books/telegrambotapi/">minidocs</a> and
<a href="https://tgbotapi.inmo.dev/docs/index.html">kdocs</a></b>
</details>
| Common info | [![Awesome Kotlin Badge](https://kotlin.link/awesome-kotlin.svg)](https://github.com/KotlinBy/awesome-kotlin) [![Build Status](https://travis-ci.com/InsanusMokrassar/TelegramBotAPI.svg?branch=master)](https://travis-ci.com/InsanusMokrassar/TelegramBotAPI) [Small survey](https://forms.gle/2Hex2ynbHWHhi1KY7)|
| Common info | [![Awesome Kotlin Badge](https://kotlin.link/awesome-kotlin.svg)](https://github.com/KotlinBy/awesome-kotlin) [![Build Status](https://github.com/InsanusMokrassar/TelegramBotAPI/workflows/Build/badge.svg)](https://github.com/InsanusMokrassar/TelegramBotAPI/actions) [Small survey](https://forms.gle/2Hex2ynbHWHhi1KY7)|
| -------------------------------------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Useful links | [![Chat in Telegram](badges/chat.svg)](https://t.me/InMoTelegramBotAPI) [![Create bot](badges/template.svg)](https://github.com/InsanusMokrassar/TelegramBotAPI-bot_template/generate) [![KDocs](badges/kdocs.svg)](https://tgbotapi.inmo.dev/docs/index.html) [Examples](https://github.com/InsanusMokrassar/TelegramBotAPI-examples/), [Mini tutorial](https://bookstack.inmo.dev/books/telegrambotapi/chapter/introduction-tutorial) |
| TelegramBotAPI Core status | [![Download](https://api.bintray.com/packages/insanusmokrassar/TelegramBotAPI/tgbotapi.core/images/download.svg)](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.core/_latestVersion) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.core) |
| TelegramBotAPI API Extensions status | [![Download](https://api.bintray.com/packages/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.api/images/download.svg)](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.api/_latestVersion) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.api/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.api) |
| TelegramBotAPI Util Extensions status | [![Download](https://api.bintray.com/packages/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.utils/images/download.svg)](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.utils/_latestVersion) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.utils/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.utils) |
| TelegramBotAPI Behaviour Builder Extensions status | [![Download](https://api.bintray.com/packages/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.behaviour_builder/images/download.svg)](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.behaviour_builder/_latestVersion) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.behaviour_builder/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.behaviour_builder) |
| TelegramBotAPI All status | [![Download](https://api.bintray.com/packages/insanusmokrassar/TelegramBotAPI/tgbotapi/images/download.svg)](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi/_latestVersion) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi) |
| TelegramBotAPI Core status | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.core) |
| TelegramBotAPI API Extensions status | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.api/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.api) |
| TelegramBotAPI Util Extensions status | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.utils/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.utils) |
| TelegramBotAPI Behaviour Builder Extensions status | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.behaviour_builder/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.behaviour_builder) |
| TelegramBotAPI All status | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi) |
**At the time of publication of version `0.28.0` there are errors in serialization plugins like
[kotlinx.serialization#1004](https://github.com/Kotlin/kotlinx.serialization/issues/1004). It is possible, that both JVM
and JS version may work improperly in some cases with `kotlinx.serialization` version `1.0.0-RC`**
## Examples
## What is it?
There are several things you need to do to launch examples below:
It is a complex of libraries for working with `TelegramBotAPI` in type-safe and strict way as much as it possible. In
the list of this complex currently next projects:
* Add `mavenCentral()` to your project repositories
* [Maven variant](https://github.com/InsanusMokrassar/TelegramBotAPI/wiki/Including-in-your-project#pomxml)
* Add dependency `implementation "dev.inmo:tgbotapi:$tgbotapi_version"`
* Replace `tgbotapi_version` with exact version (see last one in the table above) or put variable with this name in project
* Alternative variant for maven [here](https://github.com/InsanusMokrassar/TelegramBotAPI/wiki/Including-in-your-project#telegrambotapi)
* [TelegramBotAPI Core](tgbotapi.core/README.md) - core of library. In fact it is independent library and can be used alone
without any additional library
* [TelegramBotAPI API Extensions](tgbotapi.extensions.api/README.md) - contains extensions (mostly for
`RequestsExecutor`), which allows to use the core library in more pleasant way
* [TelegramBotAPI Util Extensions](tgbotapi.extensions.utils/README.md) - contains extensions for more comfortable
work with commands, updates and other different things
* [TelegramBotAPI Behaviour Builder Extensions](tgbotapi.extensions.behaviour_builder/README.md) - builder for
step-by-step handling of bot behaviour in more comfortable manner
* [TelegramBotAPI](tgbotapi/README.md) - concentration of all previously mentioned libraries
More including instructions [available here](https://github.com/InsanusMokrassar/TelegramBotAPI/wiki/Including-in-your-project).
Other configuration examples:
Most part of some specific solves or unuseful
moments are describing by official [Telegram Bot API](https://core.telegram.org/bots/api).
* [For multiplatform](https://github.com/InsanusMokrassar/TelegramBotAPI-examples/tree/master/ResenderBot)
* [For JVM](https://github.com/InsanusMokrassar/TelegramBotAPI-examples/blob/master/GetMeBot/build.gradle)
## JavaScript notes
### Most common example
### Versions before `0.28.0`
```kotlin
suspend fun main() {
val bot = telegramBot(TOKEN)
In case if you are want to use this library inside of browser, you will need additional settings (thanks for help to [Alexander Nozik](https://research.jetbrains.org/researchers/altavir)):
<details>
<summary>Gradle build script help (for versions before 0.28.0)</summary>
```groovy
dependencies {
/* ... */
implementation "com.github.insanusmokrassar:TelegramBotAPI:$tgbot_api_version"
implementation "com.github.insanusmokrassar:TelegramBotAPI-extensions-api:$tgbot_api_version" // optional
implementation "com.github.insanusmokrassar:TelegramBotAPI-extensions-utils:$tgbot_api_version" // optional
/* Block of dependencies for correct building in browser */
implementation(npm("fs"))
implementation(npm("bufferutil"))
implementation(npm("utf-8-validate"))
implementation(npm("abort-controller"))
implementation(npm("text-encoding"))
}
/* ... */
kotlin {
target {
browser {
/* Block for fix of exception in absence of some functionality, https://github.com/ktorio/ktor/issues/1339 */
dceTask {
dceOptions {
keep("ktor-ktor-io.\$\$importsForInline\$\$.ktor-ktor-io.io.ktor.utils.io")
}
}
}
bot.buildBehaviour {
println(getMe())
onCommand("start") {
reply(it, "Hi:)")
}
}.join()
}
```
</details>
In this example you will see information about this bot at the moment of starting and answer with `Hi:)` every time it
gets message `/start`
## Ok, where should I start?
### Handling only last messages
![Libraries hierarchy](resources/TelegramBotAPI-libraries-hierarchy.svg)
```kotlin
suspend fun main() {
val bot = telegramBot(TOKEN)
In most cases, the most simple way will be to implement [TelegramBotAPI](tgbotapi/README.md) - it contains
all necessary tools for comfort usage of this library. If you want to exclude some libraries, you can implement just
[TelegramBotAPI BehaviourBuilder Extensions](tgbotapi.extensions.behaviour_builder/README.md),
[TelegramBotAPI API Extensions](tgbotapi.extensions.api/README.md),
[TelegramBotAPI Util Extensions](tgbotapi.extensions.utils/README.md) or even
[TelegramBotAPI Core](tgbotapi.core/README.md).
val flowsUpdatesFilter = FlowsUpdatesFilter()
bot.buildBehaviour(flowUpdatesFilter = flowsUpdatesFilter) {
println(getMe())
onCommand("start") {
reply(it, "Hi:)")
}
If you want to dive deeper in the core of library or develop something for it - welcome to learn more from
[TelegramBotAPI Core](tgbotapi.core/README.md) and our [Telegram Chat](https://teleg.one/InMoTelegramBotAPIChat).
Anyway, all libraries are very typical inside of them. Examples:
* In `TelegramBotAPI` common request look like `requestsExecutor.execute(SomeRequest())`
* `tgbotapi.extensions.api` typical syntax look like `requestsExecutor.someRequest()` (in most cases it would be
better to use `bot` name instead of `requestsExecutor`)
* `tgbotapi.extensions.utils` will look like `filter.filterBaseMessageUpdates(chatId).filterExactCommands(Regex("^.*$"))...`
## Build instruction
If you want to build this project or to contribute, there are several recommendations:
### Build
In case if you want to just build project, run next command:
```bash
./gradlew clean build
```
On windows:
```
gradlew.bat clean build
```
### Publishing for work with your version locally
In case, if you want to work in your other projects using your modification (or some state) of this library,
you can use next code:
```bash
./gradlew clean build publishToMavenLocal
```
On windows:
```
gradlew.bat clean build publishToMavenLocal
```
But you must remember, that in this case your local maven repo must be the first one from
your project retrieving libraries:
```groovy
repositories {
mavenLocal() // that must be the first one
jcenter()
mavenCentral()
retrieveAccumulatedUpdates(this).join()
}
}
```
Besides, for your own version you can change variable `library_version` in the file [gradle.properties](./gradle.properties).
The main difference with the previous example is that bot will get only last updates (accumulated before bot launch
and maybe some updates it got after launch)
### Build a little bit more complex behaviour
```kotlin
suspend fun main() {
val bot = telegramBot(TOKEN)
bot.buildBehaviour {
println(getMe())
val nameReplyMarkup = ReplyKeyboardMarkup(
matrix {
row {
+SimpleKeyboardButton("nope")
}
}
)
onCommand("start") {
val photo = waitPhoto(
SendTextMessage(it.chat.id, "Send me your photo please")
).first()
val name = waitText(
SendTextMessage(
it.chat.id,
"Send me your name or choose \"nope\"",
replyMarkup = nameReplyMarkup
)
).first().text.takeIf { it != "nope" }
sendPhoto(
it.chat,
photo.mediaCollection,
entities = buildEntities {
if (name != null) regular(name) // may be collapsed up to name ?.let(::regular)
}
)
}
}.join()
}
```
### More examples
You may find examples in [this project](https://github.com/InsanusMokrassar/TelegramBotAPI-examples). Besides, you are
always welcome in our [wiki](https://github.com/InsanusMokrassar/TelegramBotAPI/wiki/About-this-project) and
[chat](https://t.me/InMoTelegramBotAPIChat).

View File

@@ -12,11 +12,11 @@ klock_version=2.0.6
uuid_version=0.2.3
ktor_version=1.5.1
micro_utils_version=0.4.24
micro_utils_version=0.4.25
javax_activation_version=1.1.1
library_group=dev.inmo
library_version=0.32.4
library_version=0.32.6
github_release_plugin_version=2.2.12

View File

@@ -60,6 +60,7 @@ kotlin {
dependencies {
implementation kotlin('test-common')
implementation kotlin('test-annotations-common')
implementation project(":tgbotapi.extensions.utils")
}
}

View File

@@ -16,6 +16,8 @@ import io.ktor.http.ContentType
import kotlinx.serialization.json.Json
import kotlin.collections.set
var defaultUpdateTimeoutForZeroDelay = 1000L
abstract class AbstractRequestCallFactory : KtorCallFactory {
private val methodsCache: MutableMap<String, String> = mutableMapOf()
override suspend fun <T : Any> makeCall(
@@ -41,6 +43,11 @@ abstract class AbstractRequestCallFactory : KtorCallFactory {
requestTimeoutMillis = customTimeoutMillis
socketTimeoutMillis = customTimeoutMillis
}
} else {
timeout {
requestTimeoutMillis = defaultUpdateTimeoutForZeroDelay
socketTimeoutMillis = defaultUpdateTimeoutForZeroDelay
}
}
}
}

View File

@@ -1,5 +1,7 @@
package dev.inmo.tgbotapi.types
import dev.inmo.micro_utils.common.Warning
import dev.inmo.tgbotapi.types.chat.abstracts.Chat
import kotlinx.serialization.*
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
@@ -17,9 +19,20 @@ data class ChatId(
val chatId: Identifier
) : ChatIdentifier()
val ChatId.link: String
get() = "tg://user?id=$chatId"
/**
* https://core.telegram.org/bots/api#formatting-options
*/
@Warning("This API have restrictions in Telegram System")
val Identifier.link: String
get() = "tg://user?id=$this"
/**
* https://core.telegram.org/bots/api#formatting-options
*/
@Warning("This API have restrictions in Telegram System")
val UserId.link: String
get() = chatId.link
val User.link: String
get() = id.link
typealias UserId = ChatId

View File

@@ -74,3 +74,15 @@ fun AudioFile.toInputMediaAudio(
title,
thumb ?.fileId
)
fun AudioFile.toInputMediaAudio(
textSources: TextSourcesList = emptyList(),
title: String? = this.title
): InputMediaAudio = InputMediaAudio(
fileId,
textSources,
duration,
performer,
title,
thumb ?.fileId
)

View File

@@ -70,3 +70,11 @@ fun DocumentFile.toInputMediaDocument(
parseMode,
thumb ?.fileId
)
fun DocumentFile.toInputMediaDocument(
textSources: TextSourcesList = emptyList()
) = InputMediaDocument(
fileId,
textSources,
thumb ?.fileId
)

View File

@@ -53,3 +53,10 @@ fun PhotoSize.toInputMediaPhoto(
caption,
parseMode
)
fun PhotoSize.toInputMediaPhoto(
textSources: TextSourcesList = emptyList()
): InputMediaPhoto = InputMediaPhoto(
fileId,
textSources
)

View File

@@ -1,7 +1,7 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.types.User
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.internal.*
@@ -21,6 +21,26 @@ data class TextMentionTextSource @RiskFeature(DirectInvocationOfTextSourceConstr
@Suppress("NOTHING_TO_INLINE")
inline fun mention(parts: List<TextSource>, user: User) = TextMentionTextSource(parts.makeString(), user, parts)
@Suppress("NOTHING_TO_INLINE")
inline fun User.mention(parts: List<TextSource>) = mention(parts, this)
@Suppress("NOTHING_TO_INLINE")
inline fun mention(parts: List<TextSource>, userId: UserId) = mention(parts, CommonUser(userId, ""))
@Suppress("NOTHING_TO_INLINE")
inline fun UserId.mention(parts: List<TextSource>) = mention(parts, this)
@Suppress("NOTHING_TO_INLINE")
inline fun mention(parts: List<TextSource>, id: Identifier) = mention(parts, UserId(id))
@Suppress("NOTHING_TO_INLINE")
inline fun Identifier.mention(parts: List<TextSource>) = mention(parts, this)
@Suppress("NOTHING_TO_INLINE")
inline fun mention(user: User, vararg parts: TextSource) = mention(parts.toList(), user)
@Suppress("NOTHING_TO_INLINE")
inline fun mention(text: String, user: User) = mention(user, regular(text))
@Suppress("NOTHING_TO_INLINE")
inline fun User.mention(text: String) = mention(this, regular(text))
@Suppress("NOTHING_TO_INLINE")
inline fun mention(text: String, userId: UserId) = mention(text, CommonUser(userId, ""))
@Suppress("NOTHING_TO_INLINE")
inline fun UserId.mention(text: String) = mention(text, this)
@Suppress("NOTHING_TO_INLINE")
inline fun mention(text: String, id: Identifier) = mention(text, UserId(id))
@Suppress("NOTHING_TO_INLINE")
inline fun Identifier.mention(text: String) = mention(text, this)

View File

@@ -35,12 +35,21 @@ typealias Markdown = MarkdownParseMode
typealias MarkdownV2 = MarkdownV2ParseMode
typealias HTML = HTMLParseMode
/**
* This variable respects to default parse mode used in places like next:
*
* * [dev.inmo.tgbotapi.types.message.content.TextContent.createResends]
* *
*/
var defaultParseMode: ParseMode = HTML
@Serializer(ParseMode::class)
internal object ParseModeSerializerObject : KSerializer<ParseMode> {
override fun deserialize(decoder: Decoder): ParseMode {
return when (decoder.decodeString()) {
MarkdownParseMode.parseModeName -> MarkdownParseMode
HTMLParseMode.parseModeName -> HTMLParseMode
Markdown.parseModeName -> Markdown
MarkdownV2.parseModeName -> MarkdownV2
HTML.parseModeName -> HTML
else -> throw IllegalArgumentException("Unknown parse mode")
}
}

View File

@@ -1,5 +1,6 @@
package dev.inmo.tgbotapi.types.files
import dev.inmo.tgbotapi.CommonAbstracts.TextSourcesList
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.InputMedia.InputMediaVideo
@@ -44,3 +45,15 @@ inline fun VideoFile.toInputMediaVideo(
duration,
thumb ?.fileId
)
@Suppress("NOTHING_TO_INLINE")
inline fun VideoFile.toInputMediaVideo(
textSources: TextSourcesList
) = InputMediaVideo(
fileId,
textSources,
width,
height,
duration,
thumb ?.fileId
)

View File

@@ -1,7 +1,6 @@
package dev.inmo.tgbotapi.types.message.content
import dev.inmo.tgbotapi.CommonAbstracts.TextPart
import dev.inmo.tgbotapi.CommonAbstracts.TextedInput
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.requests.send.SendTextMessage
import dev.inmo.tgbotapi.types.ChatIdentifier
@@ -10,7 +9,6 @@ import dev.inmo.tgbotapi.types.ParseMode.*
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent
import dev.inmo.tgbotapi.utils.internal.*
data class TextContent(
override val text: String,
@@ -24,8 +22,7 @@ data class TextContent(
replyMarkup: KeyboardMarkup?
): Request<ContentMessage<TextContent>> = SendTextMessage(
chatId,
toHtmlTexts().first(),
HTMLParseMode,
textSources,
false,
disableNotification,
replyToMessageId,
@@ -33,42 +30,36 @@ data class TextContent(
replyMarkup
)
@Deprecated(
"Useless due to fact that createResend currently use textSource and that will guarantee correct sending of message",
ReplaceWith("createResend")
)
override fun createResends(
chatId: ChatIdentifier,
disableNotification: Boolean,
replyToMessageId: MessageIdentifier?,
allowSendingWithoutReply: Boolean?,
replyMarkup: KeyboardMarkup?
): List<Request<ContentMessage<TextContent>>> = createResends(
chatId,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup,
HTMLParseMode
): List<Request<ContentMessage<TextContent>>> = listOf(
createResend(
chatId,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
)
@Deprecated(
"Useless due to fact that createResend currently use textSource and that will guarantee correct sending of message",
ReplaceWith("createResend")
)
fun createResends(
chatId: ChatIdentifier,
disableNotification: Boolean,
replyToMessageId: MessageIdentifier?,
allowSendingWithoutReply: Boolean?,
replyMarkup: KeyboardMarkup?,
parseMode: ParseMode = HTMLParseMode
): List<Request<ContentMessage<TextContent>>> = when (parseMode) {
is MarkdownParseMode -> toMarkdownTexts()
is MarkdownV2ParseMode -> toMarkdownV2Texts()
is HTMLParseMode -> toHtmlTexts()
}.map {
SendTextMessage(
chatId,
it,
parseMode,
false,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
}
parseMode: ParseMode = defaultParseMode
): List<Request<ContentMessage<TextContent>>> = createResends(chatId, disableNotification, replyToMessageId, allowSendingWithoutReply, replyMarkup)
}

View File

@@ -1,21 +1,16 @@
package dev.inmo.tgbotapi.types.message.content.media
import dev.inmo.tgbotapi.CommonAbstracts.CaptionedInput
import dev.inmo.tgbotapi.CommonAbstracts.TextPart
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.requests.send.media.SendAnimation
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.InputMedia.InputMediaAnimation
import dev.inmo.tgbotapi.types.MessageIdentifier
import dev.inmo.tgbotapi.types.ParseMode.HTMLParseMode
import dev.inmo.tgbotapi.types.ParseMode.MarkdownV2
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.files.AnimationFile
import dev.inmo.tgbotapi.types.files.DocumentFile
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
import dev.inmo.tgbotapi.utils.internal.toHtmlCaptions
import dev.inmo.tgbotapi.utils.internal.toMarkdownV2Captions
data class AnimationContent(
override val media: AnimationFile,
@@ -33,8 +28,7 @@ data class AnimationContent(
chatId,
media.fileId,
media.thumb ?.fileId,
toHtmlCaptions().firstOrNull(),
HTMLParseMode,
textSources,
media.duration,
media.width,
media.height,
@@ -46,8 +40,7 @@ data class AnimationContent(
override fun asInputMedia(): InputMediaAnimation = InputMediaAnimation(
media.fileId,
toMarkdownV2Captions().firstOrNull(),
MarkdownV2,
textSources,
media.width,
media.height,
media.duration,

View File

@@ -1,18 +1,17 @@
package dev.inmo.tgbotapi.types.message.content.media
import dev.inmo.tgbotapi.CommonAbstracts.TextPart
import dev.inmo.tgbotapi.CommonAbstracts.textSources
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.requests.send.media.SendAudio
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.InputMedia.InputMediaAudio
import dev.inmo.tgbotapi.types.InputMedia.toInputMediaAudio
import dev.inmo.tgbotapi.types.MessageIdentifier
import dev.inmo.tgbotapi.types.ParseMode.HTMLParseMode
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.files.AudioFile
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.content.abstracts.AudioMediaGroupContent
import dev.inmo.tgbotapi.utils.internal.toHtmlCaptions
data class AudioContent(
override val media: AudioFile,
@@ -29,8 +28,7 @@ data class AudioContent(
chatId,
media.fileId,
media.thumb ?.fileId,
toHtmlCaptions().firstOrNull(),
HTMLParseMode,
textSources,
media.duration,
media.performer,
media.title,
@@ -42,8 +40,5 @@ data class AudioContent(
override fun toMediaGroupMemberInputMedia(): InputMediaAudio = asInputMedia()
override fun asInputMedia(): InputMediaAudio = media.toInputMediaAudio(
toHtmlCaptions().firstOrNull(),
HTMLParseMode
)
override fun asInputMedia(): InputMediaAudio = media.toInputMediaAudio(textSources)
}

View File

@@ -1,21 +1,18 @@
package dev.inmo.tgbotapi.types.message.content.media
import dev.inmo.tgbotapi.CommonAbstracts.CaptionedInput
import dev.inmo.tgbotapi.CommonAbstracts.TextPart
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.requests.send.media.SendDocument
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.InputMedia.InputMediaDocument
import dev.inmo.tgbotapi.types.InputMedia.toInputMediaDocument
import dev.inmo.tgbotapi.types.MessageIdentifier
import dev.inmo.tgbotapi.types.ParseMode.HTMLParseMode
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.files.DocumentFile
import dev.inmo.tgbotapi.types.files.asDocumentFile
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.content.abstracts.DocumentMediaGroupContent
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
import dev.inmo.tgbotapi.utils.internal.toHtmlCaptions
data class DocumentContent(
override val media: DocumentFile,
@@ -32,8 +29,7 @@ data class DocumentContent(
chatId,
media.fileId,
media.thumb ?.fileId,
toHtmlCaptions().firstOrNull(),
HTMLParseMode,
textSources,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
@@ -42,10 +38,7 @@ data class DocumentContent(
override fun toMediaGroupMemberInputMedia(): InputMediaDocument = asInputMedia()
override fun asInputMedia(): InputMediaDocument = media.toInputMediaDocument(
toHtmlCaptions().firstOrNull(),
HTMLParseMode
)
override fun asInputMedia(): InputMediaDocument = media.toInputMediaDocument(textSources)
}
@Suppress("NOTHING_TO_INLINE")

View File

@@ -1,19 +1,18 @@
package dev.inmo.tgbotapi.types.message.content.media
import dev.inmo.tgbotapi.CommonAbstracts.TextPart
import dev.inmo.tgbotapi.CommonAbstracts.textSources
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.requests.send.media.SendPhoto
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.InputMedia.InputMediaPhoto
import dev.inmo.tgbotapi.types.InputMedia.toInputMediaPhoto
import dev.inmo.tgbotapi.types.MessageIdentifier
import dev.inmo.tgbotapi.types.ParseMode.HTMLParseMode
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.files.*
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaCollectionContent
import dev.inmo.tgbotapi.types.message.content.abstracts.VisualMediaGroupContent
import dev.inmo.tgbotapi.utils.internal.toHtmlCaptions
data class PhotoContent(
override val mediaCollection: Photo,
@@ -31,8 +30,7 @@ data class PhotoContent(
): Request<ContentMessage<PhotoContent>> = SendPhoto(
chatId,
media.fileId,
toHtmlCaptions().firstOrNull(),
HTMLParseMode,
textSources,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
@@ -41,8 +39,5 @@ data class PhotoContent(
override fun toMediaGroupMemberInputMedia(): InputMediaPhoto = asInputMedia()
override fun asInputMedia(): InputMediaPhoto = media.toInputMediaPhoto(
toHtmlCaptions().firstOrNull(),
HTMLParseMode
)
override fun asInputMedia(): InputMediaPhoto = media.toInputMediaPhoto(textSources)
}

View File

@@ -1,18 +1,17 @@
package dev.inmo.tgbotapi.types.message.content.media
import dev.inmo.tgbotapi.CommonAbstracts.TextPart
import dev.inmo.tgbotapi.CommonAbstracts.textSources
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.requests.send.media.SendVideo
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.InputMedia.InputMediaVideo
import dev.inmo.tgbotapi.types.MessageIdentifier
import dev.inmo.tgbotapi.types.ParseMode.HTMLParseMode
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.files.VideoFile
import dev.inmo.tgbotapi.types.files.toInputMediaVideo
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.content.abstracts.VisualMediaGroupContent
import dev.inmo.tgbotapi.utils.internal.toHtmlCaptions
data class VideoContent(
override val media: VideoFile,
@@ -29,8 +28,7 @@ data class VideoContent(
chatId,
media.fileId,
media.thumb ?.fileId,
toHtmlCaptions().firstOrNull(),
HTMLParseMode,
textSources,
media.duration,
media.width,
media.height,
@@ -43,8 +41,5 @@ data class VideoContent(
override fun toMediaGroupMemberInputMedia(): InputMediaVideo = asInputMedia()
override fun asInputMedia(): InputMediaVideo = media.toInputMediaVideo(
toHtmlCaptions().firstOrNull(),
HTMLParseMode
)
override fun asInputMedia(): InputMediaVideo = media.toInputMediaVideo(textSources)
}

View File

@@ -1,20 +1,15 @@
package dev.inmo.tgbotapi.types.message.content.media
import dev.inmo.tgbotapi.CommonAbstracts.CaptionedInput
import dev.inmo.tgbotapi.CommonAbstracts.TextPart
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.requests.send.media.SendVoice
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.InputMedia.InputMediaAudio
import dev.inmo.tgbotapi.types.MessageIdentifier
import dev.inmo.tgbotapi.types.ParseMode.HTMLParseMode
import dev.inmo.tgbotapi.types.ParseMode.MarkdownV2
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.files.VoiceFile
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
import dev.inmo.tgbotapi.utils.internal.toHtmlCaptions
import dev.inmo.tgbotapi.utils.internal.toMarkdownV2Captions
data class VoiceContent(
override val media: VoiceFile,
@@ -30,8 +25,7 @@ data class VoiceContent(
): Request<ContentMessage<VoiceContent>> = SendVoice(
chatId,
media.fileId,
toHtmlCaptions().firstOrNull(),
HTMLParseMode,
textSources,
media.duration,
disableNotification,
replyToMessageId,
@@ -41,8 +35,7 @@ data class VoiceContent(
override fun asInputMedia(): InputMediaAudio = InputMediaAudio(
media.fileId,
toMarkdownV2Captions().firstOrNull(),
MarkdownV2,
textSources,
media.duration
)
}

View File

@@ -1,97 +0,0 @@
package dev.inmo.tgbotapi.utils.internal
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.types.ParseMode.*
import dev.inmo.tgbotapi.types.captionLength
import dev.inmo.tgbotapi.types.message.content.TextContent
import dev.inmo.tgbotapi.types.textLength
internal fun createFormattedText(
entities: TextSourcesList,
partLength: Int = textLength.last,
mode: ParseMode = MarkdownParseMode
): List<String> {
val texts = mutableListOf<String>()
val textBuilder = StringBuilder(partLength)
for (entity in entities) {
val string = when (mode) {
is MarkdownParseMode -> entity.markdown
is MarkdownV2ParseMode -> entity.markdownV2
is HTMLParseMode -> entity.html
}
if (textBuilder.length + string.length > partLength) {
if (textBuilder.isNotEmpty()) {
texts.add(textBuilder.toString())
textBuilder.clear()
}
val chunked = string.chunked(partLength)
val last = chunked.last()
textBuilder.append(last)
val listToAdd = if (chunked.size > 1) {
chunked.subList(0, chunked.size - 1)
} else {
emptyList()
}
listToAdd.forEach {
texts.add(it)
}
} else {
textBuilder.append(string)
}
}
if (textBuilder.isNotEmpty()) {
texts.add(textBuilder.toString())
textBuilder.clear()
}
return texts
}
internal fun createMarkdownText(
entities: TextSourcesList,
partLength: Int = textLength.last
): List<String> = createFormattedText(entities, partLength, MarkdownParseMode)
internal fun TextSourcesList.toMarkdownTexts(): List<String> = createMarkdownText(
this,
textLength.last
)
internal fun TextContent.toMarkdownTexts(): List<String> = textSources.toMarkdownTexts()
internal fun createMarkdownV2Text(
entities: TextSourcesList,
partLength: Int = textLength.last
): List<String> = createFormattedText(entities, partLength, MarkdownV2ParseMode)
internal fun TextSourcesList.toMarkdownV2Captions(): List<String> = createMarkdownV2Text(
this,
captionLength.last
)
internal fun CaptionedInput.toMarkdownV2Captions(): List<String> = textSources.toMarkdownV2Captions()
internal fun TextSourcesList.toMarkdownV2Texts(): List<String> = createMarkdownV2Text(
this,
textLength.last
)
internal fun TextContent.toMarkdownV2Texts(): List<String> = textSources.toMarkdownV2Texts()
internal fun createHtmlText(
entities: TextSourcesList,
partLength: Int = textLength.last
): List<String> = createFormattedText(entities, partLength, HTMLParseMode)
internal fun TextSourcesList.toHtmlCaptions(): List<String> = createHtmlText(
this,
captionLength.last
)
internal fun CaptionedInput.toHtmlCaptions(): List<String> = textSources.toHtmlCaptions()
internal fun TextSourcesList.toHtmlTexts(): List<String> = createHtmlText(
this,
textLength.last
)
internal fun TextContent.toHtmlTexts(): List<String> = textSources.toHtmlTexts()

View File

@@ -2,8 +2,8 @@ package dev.inmo.tgbotapi.types.MessageEntity
import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.plus
import dev.inmo.tgbotapi.extensions.utils.formatting.*
import dev.inmo.tgbotapi.types.MessageEntity.textsources.*
import dev.inmo.tgbotapi.utils.internal.*
import kotlin.test.Test
import kotlin.test.assertEquals

View File

@@ -1,8 +1,8 @@
package dev.inmo.tgbotapi.types.MessageEntity
import dev.inmo.tgbotapi.CommonAbstracts.justTextSources
import dev.inmo.tgbotapi.utils.internal.toHtmlTexts
import dev.inmo.tgbotapi.utils.internal.toMarkdownV2Texts
import dev.inmo.tgbotapi.extensions.utils.formatting.toHtmlTexts
import dev.inmo.tgbotapi.extensions.utils.formatting.toMarkdownV2Texts
import kotlin.test.Test
import kotlin.test.assertEquals

View File

@@ -29,10 +29,18 @@ suspend fun TelegramBot.sendDice(
replyMarkup: KeyboardMarkup? = null
) = sendDice(chat.id, animationType, disableNotification, replyToMessageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.reply(
suspend inline fun TelegramBot.replyWithDice(
to: Message,
animationType: DiceAnimationType? = null,
disableNotification: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendDice(to.chat, animationType, disableNotification, to.messageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.reply(
to: Message,
animationType: DiceAnimationType? = null,
disableNotification: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = replyWithDice(to, animationType, disableNotification, allowSendingWithoutReply, replyMarkup)

View File

@@ -44,5 +44,23 @@ kotlin {
api project(":tgbotapi.core")
}
}
commonTest {
dependencies {
implementation kotlin('test-common')
implementation kotlin('test-annotations-common')
}
}
jvmTest {
dependencies {
implementation kotlin('test-junit')
}
}
jsTest {
dependencies {
implementation kotlin('test-junit')
implementation kotlin('test-js')
}
}
}
}

View File

@@ -6,16 +6,30 @@ import dev.inmo.tgbotapi.types.dice.SlotMachineDiceAnimationType
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
enum class SlotMachineReelImages {
BAR, BERRIES, LEMON, SEVEN
/**
* @param text Is a text representation
* @param number Internal representation of reel
*/
enum class SlotMachineReelImage(val text: String, val number: Int) {
BAR("[bar]", 0),
BERRIES("\uD83C\uDF52", 1),
LEMON("\uD83C\uDF4B", 2),
SEVEN("7", 3)
}
@Deprecated("Renamed", ReplaceWith("SlotMachineReelImage", "dev.inmo.tgbotapi.extensions.utils.SlotMachineReelImage"))
typealias SlotMachineReelImages = SlotMachineReelImage
/**
* @return First [SlotMachineReelImage] with [SlotMachineReelImage.number] equal to receiver OR [SlotMachineReelImage.SEVEN]
*/
val Int.asSlotMachineReelImage
get() = when (this) {
0 -> SlotMachineReelImages.BAR
1 -> SlotMachineReelImages.BERRIES
2 -> SlotMachineReelImages.LEMON
else -> SlotMachineReelImages.SEVEN
}
get() = SlotMachineReelImage.values().firstOrNull { it.number == this } ?: SlotMachineReelImage.SEVEN
/**
* @return First [SlotMachineReelImage] with [SlotMachineReelImage.text] equal to receiver OR [SlotMachineReelImage.SEVEN]
*/
val String.asSlotMachineReelImage
get() = SlotMachineReelImage.values().firstOrNull { it.text == this } ?: SlotMachineReelImage.SEVEN
@Serializable
data class SlotMachineResult(

View File

@@ -8,15 +8,15 @@ import dev.inmo.tgbotapi.types.message.content.TextContent
fun createFormattedText(
entities: TextSourcesList,
partLength: Int = textLength.last,
mode: ParseMode = MarkdownParseMode
mode: ParseMode = defaultParseMode
): List<String> {
val texts = mutableListOf<String>()
val textBuilder = StringBuilder(partLength)
for (entity in entities) {
val string = when (mode) {
is MarkdownParseMode -> entity.markdown
is MarkdownV2ParseMode -> entity.markdownV2
is HTMLParseMode -> entity.html
is Markdown -> entity.markdown
is MarkdownV2 -> entity.markdownV2
is HTML -> entity.html
}
if (textBuilder.length + string.length > partLength) {
if (textBuilder.isNotEmpty()) {
@@ -49,7 +49,7 @@ fun createFormattedText(
fun createMarkdownText(
entities: TextSourcesList,
partLength: Int = textLength.last
): List<String> = createFormattedText(entities, partLength, MarkdownParseMode)
): List<String> = createFormattedText(entities, partLength, Markdown)
fun TextSourcesList.toMarkdownCaptions(): List<String> = createMarkdownText(
this,
@@ -73,7 +73,7 @@ fun ExplainedInput.toMarkdownExplanations(): List<String> = textSources.toMarkdo
fun createMarkdownV2Text(
entities: TextSourcesList,
partLength: Int = textLength.last
): List<String> = createFormattedText(entities, partLength, MarkdownV2ParseMode)
): List<String> = createFormattedText(entities, partLength, MarkdownV2)
fun TextSourcesList.toMarkdownV2Captions(): List<String> = createMarkdownV2Text(
this,
@@ -97,7 +97,7 @@ fun ExplainedInput.toMarkdownV2Explanations(): List<String> = textSources.toMark
fun createHtmlText(
entities: TextSourcesList,
partLength: Int = textLength.last
): List<String> = createFormattedText(entities, partLength, HTMLParseMode)
): List<String> = createFormattedText(entities, partLength, HTML)
fun TextSourcesList.toHtmlCaptions(): List<String> = createHtmlText(
this,

View File

@@ -1,7 +1,6 @@
package dev.inmo.tgbotapi.extensions.utils.updates.retrieving
import dev.inmo.micro_utils.coroutines.ExceptionHandler
import dev.inmo.micro_utils.coroutines.safely
import dev.inmo.micro_utils.coroutines.*
import dev.inmo.tgbotapi.bot.RequestsExecutor
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.bot.exceptions.RequestException
@@ -14,7 +13,11 @@ import dev.inmo.tgbotapi.types.update.MediaGroupUpdates.*
import dev.inmo.tgbotapi.types.update.abstracts.Update
import dev.inmo.tgbotapi.updateshandlers.*
import dev.inmo.tgbotapi.utils.*
import io.ktor.client.features.HttpRequestTimeoutException
import io.ktor.utils.io.core.use
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlin.coroutines.coroutineContext
fun TelegramBot.startGettingOfUpdatesByLongPolling(
timeoutSeconds: Seconds = 30,
@@ -66,6 +69,70 @@ fun TelegramBot.startGettingOfUpdatesByLongPolling(
}
}
fun TelegramBot.retrieveAccumulatedUpdates(
avoidInlineQueries: Boolean = false,
avoidCallbackQueries: Boolean = false,
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
exceptionsHandler: (ExceptionHandler<Unit>)? = null,
allowedUpdates: List<String>? = null,
updatesReceiver: UpdateReceiver<Update>
): Job = scope.launch {
safelyWithoutExceptions {
startGettingOfUpdatesByLongPolling(
0,
CoroutineScope(coroutineContext + SupervisorJob()),
{
if (it is HttpRequestTimeoutException) {
throw CancellationException("Cancel due to absence of new updates")
} else {
exceptionsHandler ?.invoke(it)
}
},
allowedUpdates
) {
when {
it is InlineQueryUpdate && avoidInlineQueries ||
it is CallbackQueryUpdate && avoidCallbackQueries -> return@startGettingOfUpdatesByLongPolling
else -> updatesReceiver(it)
}
}.join()
}
}
/**
* @return [kotlinx.coroutines.flow.Flow] which will emit updates to the collector while they will be accumulated. Works
* the same as [retrieveAccumulatedUpdates], but pass [kotlinx.coroutines.flow.FlowCollector.emit] as a callback
*/
fun TelegramBot.createAccumulatedUpdatesRetrieverFlow(
avoidInlineQueries: Boolean = false,
avoidCallbackQueries: Boolean = false,
exceptionsHandler: ExceptionHandler<Unit>? = null,
allowedUpdates: List<String>? = null
): Flow<Update> = channelFlow {
val parentContext = kotlin.coroutines.coroutineContext
channel.apply {
retrieveAccumulatedUpdates(
avoidInlineQueries,
avoidCallbackQueries,
CoroutineScope(parentContext),
exceptionsHandler,
allowedUpdates,
::send
).join()
close()
}
}
fun TelegramBot.retrieveAccumulatedUpdates(
flowsUpdatesFilter: FlowsUpdatesFilter,
avoidInlineQueries: Boolean = false,
avoidCallbackQueries: Boolean = false,
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
exceptionsHandler: ExceptionHandler<Unit>? = null
) = flowsUpdatesFilter.run {
retrieveAccumulatedUpdates(avoidInlineQueries, avoidCallbackQueries, scope, exceptionsHandler, allowedUpdates, asUpdateReceiver)
}
/**
* Will [startGettingOfUpdatesByLongPolling] using incoming [flowsUpdatesFilter]. It is assumed that you ALREADY CONFIGURE
* all updates receivers, because this method will trigger getting of updates and.