1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2025-11-17 04:20:13 +00:00

Compare commits

...

124 Commits

Author SHA1 Message Date
69683a4e6a upfill changelog 2023-03-11 22:38:09 +06:00
e5a48e9684 rework of multipart files with fixes in new sticker sets 2023-03-11 21:17:59 +06:00
6722ab5f50 add several extensions for addStickerToSet 2023-03-11 17:58:48 +06:00
810b2ab5a1 add Sticker#asInputSticker 2023-03-11 17:39:12 +06:00
5992fdd456 Update Sticker.kt 2023-03-11 01:30:12 +06:00
3c4f8787a6 mask position is nullable in mask stickers and sticker sets 2023-03-11 01:18:39 +06:00
0c24aa1270 add sticker format to stickerset 2023-03-11 00:53:36 +06:00
988d9995c5 add sticker format to sticker object 2023-03-11 00:46:20 +06:00
f75df0a425 Update microutils 2023-03-10 22:34:48 +06:00
9f14eb2ca3 update microutils 2023-03-10 15:08:44 +06:00
6f9f880b79 deprecations removing 2023-03-10 14:59:59 +06:00
2d2310daca fixes in build 2023-03-10 14:43:34 +06:00
dff04d26ca add support of setCustomEmojiStickerSetThumbnail 2023-03-10 14:29:55 +06:00
4390c12180 update uploadStickerFile 2023-03-10 14:24:42 +06:00
1b4d13e452 rework of addStickerToSet 2023-03-10 14:20:34 +06:00
afda5e0e7f rework of create new sticker set 2023-03-10 14:00:57 +06:00
cd354e9456 upgrade version up to 7.0.0 2023-03-10 13:40:15 +06:00
b0e32e8ad9 add opportunity to send emoji with sticker 2023-03-10 12:43:09 +06:00
79c9e6258f add setStickerMaskPosition 2023-03-10 12:28:16 +06:00
90b9c66bea rename all thumb* usages 2023-03-10 12:24:12 +06:00
e7b21dcd3d rename setStickerSetThumb to setStickerSetThumbnail 2023-03-10 12:11:17 +06:00
e30361ad1e rename thumb field 2023-03-10 12:02:40 +06:00
d8c659f866 add setStickerKeywords 2023-03-10 11:32:44 +06:00
5533303d86 add setStickerEmojiList 2023-03-10 11:28:21 +06:00
1633b9baaf add deleteStickerSet 2023-03-10 11:18:37 +06:00
a9725eb439 add support of setStickerSetTitle 2023-03-10 11:16:13 +06:00
a0aadef31b add support of localized bot description 2023-03-10 00:34:57 +06:00
ac88fd1d02 start 6.2.0 2023-03-10 00:23:16 +06:00
e3e318312d Merge pull request #734 from InsanusMokrassar/6.1.0
6.1.0
2023-03-08 17:10:47 +06:00
4c08fb7d26 small improvement in #732 solution 2023-03-08 16:41:10 +06:00
d83ff12560 update dependencies 2023-03-08 16:38:24 +06:00
818ef8481d fix of #732 2023-03-08 16:33:41 +06:00
f8cd446133 start 6.1.0 2023-03-08 16:24:31 +06:00
804b991921 update kdocs 2023-03-04 21:18:50 +06:00
817068aa71 Merge pull request #731 from InsanusMokrassar/renovate/dokka
Update dependency org.jetbrains.dokka:dokka-gradle-plugin to v1.8.10
2023-03-04 10:48:42 +06:00
renovate[bot]
0cca343612 Update dependency org.jetbrains.dokka:dokka-gradle-plugin to v1.8.10 2023-03-04 03:54:29 +00:00
6532bf255b Merge pull request #730 from InsanusMokrassar/6.0.3
6.0.3
2023-03-02 23:28:16 +06:00
421d5ae9e3 Update CHANGELOG.md 2023-03-02 21:59:58 +06:00
54f1181a14 Update libs.versions.toml 2023-03-02 21:59:26 +06:00
f616a02f7c hotfixes 2023-03-02 20:33:49 +06:00
f1deb93147 changes in InlineQuery 2023-03-02 19:33:15 +06:00
2300b44aae fix in CallbackQuery 2023-03-02 12:43:39 +06:00
fe88cf037a fixes in deeplinks 2023-03-02 08:32:06 +06:00
89920abe35 start 6.0.3 2023-03-02 08:31:35 +06:00
4c4aa491cb Merge pull request #729 from InsanusMokrassar/6.0.2
6.0.2
2023-03-01 15:33:43 +06:00
f0a4425be9 Update CHANGELOG.md 2023-03-01 15:31:34 +06:00
6c8af4cab3 fixes in media groups collecting and kdocs 2023-03-01 13:14:18 +06:00
017d57e5e5 fixes 2023-03-01 12:38:50 +06:00
5a456bcdbf add opportunity to collect media groups with debounce 2023-03-01 11:55:17 +06:00
4182d8f3fe start 6.0.2 2023-03-01 00:59:08 +06:00
c6e2cba09b Merge pull request #728 from InsanusMokrassar/6.0.1
6.0.1
2023-02-28 20:41:35 +06:00
8dd3eefd15 Update CHANGELOG.md 2023-02-28 19:59:23 +06:00
b72d4da8f0 Update libs.versions.toml 2023-02-28 19:57:11 +06:00
ebd023669d start 6.0.1 2023-02-28 19:55:29 +06:00
f7be4e557e Merge pull request #726 from InsanusMokrassar/6.0.0
6.0.0
2023-02-28 13:27:41 +06:00
ec434c6af4 fill changelog with dependencies updates 2023-02-27 22:42:28 +06:00
0398590de6 update microutils version to release one 2023-02-27 22:40:26 +06:00
9ef1b54ada *.link renames 2023-02-27 22:32:08 +06:00
c30ce5c803 revert gradle wrapper version 2023-02-27 20:10:45 +06:00
c0a50bccb0 update publish.gradle and gradle wrapper version 2023-02-27 18:40:01 +06:00
e0cd7dc512 TelegramBot.resend 2023-02-27 18:27:23 +06:00
6ff621b428 Add triggers and waiters for VisualMediaGroupPartContent 2023-02-27 18:10:33 +06:00
964a61749c update dependencies 2023-02-27 17:57:32 +06:00
17930091ac start 6.0.0 2023-02-27 17:55:49 +06:00
2271beadfb Update README.md 2023-02-24 15:31:33 +06:00
44c48a8462 Add files via upload 2023-02-24 15:30:36 +06:00
4d35f89ad1 Merge pull request #722 from InsanusMokrassar/5.2.1
5.2.1
2023-02-21 21:44:53 +06:00
174706b189 changelog fill and callback query improvements 2023-02-19 18:35:36 +06:00
fe17312bb5 Update LiveFlowLocation.kt 2023-02-17 15:50:49 +06:00
d8b5789cd2 5.2.1 2023-02-17 15:48:02 +06:00
f27d0916db Merge pull request #721 from InsanusMokrassar/5.2.0
hotfix in LiveFlowLocation (5.2.0)
2023-02-17 15:42:17 +06:00
fa0a2818a0 hotfix in LiveFlowLocation 2023-02-17 15:40:49 +06:00
2d3fe45389 Merge pull request #720 from InsanusMokrassar/5.2.0
5.2.0
2023-02-17 15:36:27 +06:00
02b5d282d3 now it is possible to handle send content message in handleLiveLocation 2023-02-17 15:31:40 +06:00
7795bc2b50 LiveLocationProvider#message now is public, but as value instead of variable 2023-02-17 15:28:41 +06:00
a95365a691 update microutils up to 0.16.10 2023-02-17 14:03:00 +06:00
07082bf896 start 5.2.0 2023-02-17 14:02:18 +06:00
6a3fc47f62 Merge pull request #717 from InsanusMokrassar/5.1.1
5.1.1
2023-02-17 14:01:21 +06:00
1c94e86b40 small improvements 2023-02-13 12:06:28 +06:00
0416b200b8 fixes :) 2023-02-13 12:03:23 +06:00
48c4e90912 fixes 2023-02-13 12:00:09 +06:00
5fc88e89b9 Fixes in content waiting expectators 2023-02-13 11:49:36 +06:00
dad42cf939 makeUserLink 2023-02-13 11:16:49 +06:00
041c3ecc1b start 5.1.1 2023-02-11 18:57:46 +06:00
103dd949ce Merge pull request #712 from InsanusMokrassar/5.1.0
5.1.0
2023-02-06 14:08:03 +06:00
e3acdf1802 fix of #697 2023-02-06 13:28:38 +06:00
f81d28dd5f fill changelog and fix several issues 2023-02-06 12:41:19 +06:00
8e02a702f1 improvements in ChatPermissions 2023-02-06 12:04:30 +06:00
cb7a343208 improve copying functions in chat permissions 2023-02-06 11:36:00 +06:00
3be8ddae74 rights copying hotfix 2023-02-06 11:29:07 +06:00
9cd1862300 add opportunity to copy chat permissions 2023-02-06 11:25:31 +06:00
81fdf50217 ChatPermissions now is interface 2023-02-06 10:26:48 +06:00
554d47e301 Update README.md 2023-02-06 00:59:33 +06:00
b66ae7ad77 Update README.md 2023-02-06 00:58:36 +06:00
4ddced8e26 Merge pull request #715 from madhead/feature/replace_can_send_media_messages_field
Replaced the fields `can_send_media_messages`…
2023-02-06 00:25:40 +06:00
d003047a6c Merge branch '5.1.0' into feature/replace_can_send_media_messages_field 2023-02-06 00:24:19 +06:00
1e4a78c812 add support for independent chat permissions 2023-02-06 00:21:46 +06:00
2a3ffd707e improvements in KeyboardButtonRequestChat 2023-02-05 23:41:02 +06:00
aca076381b renames in request buttons 2023-02-05 23:26:41 +06:00
12ac227d2d small fix in request chat button 2023-02-05 23:18:14 +06:00
e235280253 fixes in RequestId 2023-02-05 22:29:21 +06:00
0da0c4e894 Revert "fixes in keyboards"
This reverts commit ae8ef0dd3c.
2023-02-05 22:25:43 +06:00
47f1509ecc add RequestId.random 2023-02-05 22:01:43 +06:00
ae8ef0dd3c fixes in keyboards 2023-02-05 21:47:15 +06:00
687f9e95fa support of user shared/chat shared 2023-02-05 20:46:25 +06:00
6dbe5f024f Merge pull request #713 from madhead/feature/user_chat_id_in_chat_join_request
Add support for `user_chat_id` field
2023-02-05 18:34:36 +06:00
a39a276299 Update libs.versions.toml 2023-02-05 18:34:05 +06:00
9f57e5685f Merge branch '5.1.0' into feature/user_chat_id_in_chat_join_request 2023-02-05 18:33:43 +06:00
bdcba202c9 Update ChatJoinRequest.kt 2023-02-05 18:32:46 +06:00
3c48dcb2a6 downgrade kotlin 2023-02-05 18:26:29 +06:00
b59d94d0a9 Update libs.versions.toml 2023-02-05 17:41:45 +06:00
db74b55c41 Update CHANGELOG.md 2023-02-05 17:41:45 +06:00
37b5af235a start 5.1.0 2023-02-05 17:41:07 +06:00
e2b05ce575 Merge pull request #711 from InsanusMokrassar/5.0.2
5.0.2
2023-02-05 17:34:42 +06:00
49851ee3d7 update micro_utils version 2023-02-05 16:22:33 +06:00
madhead
cd596cc66d Replaced the fields can_send_media_messages in the classes RestrictedChatMember and ChatPermissions with separate fields can_send_audios, can_send_documents, can_send_photos, can_send_videos, can_send_video_notes, and can_send_voice_notes for different media types. 2023-02-03 22:16:21 +01:00
madhead
5667ae8095 Added the field user_chat_id to the class ChatJoinRequest. 2023-02-03 21:26:55 +01:00
f29996aac8 Update libs.versions.toml 2023-02-04 00:56:47 +06:00
32613bacc6 Update CHANGELOG.md 2023-02-04 00:56:06 +06:00
cf9dba0ecc start 5.1.0 2023-02-04 00:55:46 +06:00
a8c4879769 update dependencies 2023-02-02 09:25:21 +06:00
f083e94c05 fix in BehaviourContext.onEditedContentMessage 2023-02-02 09:24:16 +06:00
c332413e5a start 5.0.2 2023-02-02 09:21:57 +06:00
c9f3d99cd7 Merge pull request #708 from InsanusMokrassar/5.0.1
5.0.1
2023-01-18 23:45:19 +06:00
188 changed files with 3512 additions and 2653 deletions

View File

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

View File

@@ -1,10 +1,112 @@
# TelegramBotAPI changelog # TelegramBotAPI changelog
## 7.0.0
This update contains support of [Telegram Bot API 6.6](https://core.telegram.org/bots/api-changelog#march-9-2023)
**THIS VERSION CONTAINS BREAKING CHANGES**:
* All previous deprecations have been removed
* Fully reworked mechanism of stickers creating and adding
* All separations of stickers types like `Animeted` have been replaces with type `StickerFormat`
* New `InputSticker` type (and all subtypes) as replacements for old raw fields in methods
* Reworked mechanism of files uploading
Other changes
* `Versions`:
* `MicroUtils`: `0.17.3` -> `0.17.5`
## 6.1.0
* `Versions`:
* `MicroUtils`: `0.17.2` -> `0.17.3`
* `API`:
* Fix of [#732](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/732)
## 6.0.3
* `Versions`:
* `MicroUtils`: `0.17.1` -> `0.17.2`
* `Core`:
* `User` in `CallbackQuery` now is `CommonUser` as well as in `from`
* `User` in `InlineQuery` now is `CommonUser` as well as in `from`
* `BehaviourBuilder`:
* Fixes in `DeepLink` triggers and waiters
## 6.0.2
* `Core`:
* Long polling now uses media groups debounce as in webhooks
## 6.0.1
* `Versions`:
* `Ktor`: `2.2.3` -> `2.2.4`
* `MicroUtils`: `0.17.0` -> `0.17.1`
## 6.0.0
* `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
* `Versions`:
* `MicroUtils`: `0.16.8` -> `0.16.10`
## 5.1.1
* `Core`:
* Add opportunity to get user link with `makeUserLink`
* `BehaviourBuilder`:
* Fixes in content waiting expectators
## 5.1.0
[Bot API 6.5](https://core.telegram.org/bots/api-changelog#february-3-2023) support
* `Core`:
* `ChatPermissions` now is interface and have two main realizations: `ChatPermissions.Granular` and
`ChatPermissions.Common`
* `RestrictedChatMember` now implements `ChatPermissions` too
* `API`:
* Now it is possible to pass all long polling parameters in all places used it
* `Issues`:
* Fix of [#697](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/697)
## 5.0.2
* `Versions`:
* `MicroUtils`: `0.16.6` -> `0.16.8`
* `Ktor`: `2.2.2` -> `2.2.3`
* `BehaviourBuilder`:
* Fixes in `BehaviourContext.onEditedContentMessage` - now it will trigger callback on channel post edits too
## 5.0.1 ## 5.0.1
* `Versions`: * `Versions`:
* `MicroUtils`: `0.16.4` -> `0.16.6` * `MicroUtils`: `0.16.4` -> `0.16.6`
* `Ktor`: `2.2.1` -> `2.2.2` * `Ktor`: `2.2.1` -> `2.2.2`
* `Core`: * `Core`:
* Fixes in `SendMediaGroup` request * Fixes in `SendMediaGroup` request
* Fixes in `SetChatAdministratorCustomTitle` request (thanks to [@madhead](https://github.com/madhead)) * Fixes in `SetChatAdministratorCustomTitle` request (thanks to [@madhead](https://github.com/madhead))

View File

@@ -1,14 +1,14 @@
# TelegramBotAPI [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi) [![Supported version](https://img.shields.io/badge/Telegram%20Bot%20API-6.4-blue)](https://core.telegram.org/bots/api-changelog#december-30-2022) # TelegramBotAPI [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi) [![Supported version](https://img.shields.io/badge/Telegram%20Bot%20API-6.6-blue)](https://core.telegram.org/bots/api-changelog#march-9-2023)
| Docs | [![KDocs](https://img.shields.io/static/v1?label=Dokka&message=KDocs&color=blue&logo=kotlin)](https://tgbotapi.inmo.dev/index.html) [![Mini tutorial](https://img.shields.io/static/v1?label=Bookstack&message=Tutorial&color=blue&logo=bookstack)](https://bookstack.inmo.dev/books/telegrambotapi/chapter/introduction-tutorial) | | Docs | [![KDocs](https://img.shields.io/static/v1?label=Dokka&message=KDocs&color=blue&logo=kotlin)](https://tgbotapi.inmo.dev/index.html) [![Mini tutorial](https://img.shields.io/static/v1?label=Bookstack&message=Tutorial&color=blue&logo=bookstack)](https://bookstack.inmo.dev/books/telegrambotapi/chapter/introduction-tutorial) |
|:---:|:---:| |:---:|:---:|
| Useful repos | [![Create bot](https://img.shields.io/static/v1?label=Github&message=Template&color=blue&logo=github)](https://github.com/InsanusMokrassar/TelegramBotAPI-bot_template/generate) [![Examples](https://img.shields.io/static/v1?label=Github&message=Examples&color=blue&logo=github)](https://github.com/InsanusMokrassar/TelegramBotAPI-examples/) | | Useful repos | [![Create bot](https://img.shields.io/static/v1?label=Github&message=Template&color=blue&logo=github)](https://github.com/InsanusMokrassar/TelegramBotAPI-bot_template/generate) [![Examples](https://img.shields.io/static/v1?label=Github&message=Examples&color=blue&logo=github)](https://github.com/InsanusMokrassar/TelegramBotAPI-examples/) |
| Misc | [![Awesome Kotlin Badge](https://kotlin.link/awesome-kotlin.svg)](https://github.com/KotlinBy/awesome-kotlin) [![Small survey](https://img.shields.io/static/v1?label=Google&message=Survey&color=blue&logo=google-sheets)](https://docs.google.com/forms/d/e/1FAIpQLSctdJHT_aEniyYT0-IUAEfo1hsIlezX2owlkEAYX4KPl2V2_A/viewform?usp=sf_link) | | Misc | [![Awesome Kotlin Badge](https://kotlin.link/awesome-kotlin.svg)](https://github.com/KotlinBy/awesome-kotlin) [![Small survey](https://img.shields.io/static/v1?label=Google&message=Survey&color=blue&logo=google-sheets)](https://docs.google.com/forms/d/e/1FAIpQLSctdJHT_aEniyYT0-IUAEfo1hsIlezX2owlkEAYX4KPl2V2_A/viewform?usp=sf_link) |
<!--- [![Telegram Channel](./resources/tg_channel_qr.jpg)](https://t.me/InMoTelegramBotAPI) ---> <!--- [![Telegram Channel](./resources/tg_channel_qr.jpg)](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>

View File

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

View File

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

View File

@@ -1,22 +1,22 @@
[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.2" 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.6" microutils = "0.17.5"
github-release-plugin = "2.4.1" github-release-plugin = "2.4.1"
dokka = "1.7.20" dokka = "1.8.10"
[libraries] [libraries]
@@ -45,6 +45,7 @@ microutils-coroutines = { module = "dev.inmo:micro_utils.coroutines", version.re
microutils-serialization-base64 = { module = "dev.inmo:micro_utils.serialization.base64", version.ref = "microutils" } microutils-serialization-base64 = { module = "dev.inmo:micro_utils.serialization.base64", version.ref = "microutils" }
microutils-serialization-encapsulator = { module = "dev.inmo:micro_utils.serialization.encapsulator", version.ref = "microutils" } microutils-serialization-encapsulator = { module = "dev.inmo:micro_utils.serialization.encapsulator", version.ref = "microutils" }
microutils-serialization-typedSerializer = { module = "dev.inmo:micro_utils.serialization.typed_serializer", version.ref = "microutils" } microutils-serialization-typedSerializer = { module = "dev.inmo:micro_utils.serialization.typed_serializer", version.ref = "microutils" }
microutils-serialization-mapper = { module = "dev.inmo:micro_utils.serialization.mapper", version.ref = "microutils" }
microutils-languageCodes = { module = "dev.inmo:micro_utils.language_codes", version.ref = "microutils" } microutils-languageCodes = { module = "dev.inmo:micro_utils.language_codes", version.ref = "microutils" }
microutils-ktor-common = { module = "dev.inmo:micro_utils.ktor.common", version.ref = "microutils" } microutils-ktor-common = { module = "dev.inmo:micro_utils.ktor.common", version.ref = "microutils" }
microutils-fsm-common = { module = "dev.inmo:micro_utils.fsm.common", version.ref = "microutils" } microutils-fsm-common = { module = "dev.inmo:micro_utils.fsm.common", version.ref = "microutils" }
@@ -67,3 +68,4 @@ github-release-plugin = { module = "com.github.breadmoirai:github-release", vers
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
kotlin-dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }

View File

@@ -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

View File

@@ -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

View File

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

View File

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

View File

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

View File

@@ -6,7 +6,6 @@ import dev.inmo.tgbotapi.abstracts.*
import dev.inmo.tgbotapi.abstracts.types.WithReplyMarkup import dev.inmo.tgbotapi.abstracts.types.WithReplyMarkup
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.api.edit.edit import dev.inmo.tgbotapi.extensions.api.edit.edit
import dev.inmo.tgbotapi.extensions.api.edit.location.live.editLiveLocation
import dev.inmo.tgbotapi.extensions.api.send.send import dev.inmo.tgbotapi.extensions.api.send.send
import dev.inmo.tgbotapi.extensions.api.send.sendLiveLocation import dev.inmo.tgbotapi.extensions.api.send.sendLiveLocation
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
@@ -17,6 +16,7 @@ import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.content.LocationContent import dev.inmo.tgbotapi.types.message.content.LocationContent
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlin.js.JsName import kotlin.js.JsName
@@ -45,7 +45,8 @@ suspend fun TelegramBot.handleLiveLocation(
disableNotification: Boolean = false, disableNotification: Boolean = false,
protectContent: Boolean = false, protectContent: Boolean = false,
replyToMessageId: MessageId? = null, replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null allowSendingWithoutReply: Boolean? = null,
sentMessageFlow: FlowCollector<ContentMessage<LocationContent>>? = null
) { ) {
var currentLiveLocationMessage: ContentMessage<LocationContent>? = null var currentLiveLocationMessage: ContentMessage<LocationContent>? = null
val updateMessageJob = CoroutineScope(currentCoroutineContext().LinkedSupervisorJob()).launchSafelyWithoutExceptions(start = CoroutineStart.LAZY) { val updateMessageJob = CoroutineScope(currentCoroutineContext().LinkedSupervisorJob()).launchSafelyWithoutExceptions(start = CoroutineStart.LAZY) {
@@ -73,7 +74,9 @@ suspend fun TelegramBot.handleLiveLocation(
replyToMessageId, replyToMessageId,
allowSendingWithoutReply, allowSendingWithoutReply,
it.replyMarkup it.replyMarkup
) ).also {
sentMessageFlow ?.emit(it)
}
} else { } else {
edit( edit(
capturedLiveLocationMessage, capturedLiveLocationMessage,
@@ -83,7 +86,9 @@ suspend fun TelegramBot.handleLiveLocation(
it.heading, it.heading,
it.proximityAlertRadius, it.proximityAlertRadius,
it.replyMarkup it.replyMarkup
) ).also {
sentMessageFlow ?.emit(it)
}
} }
} }
} }
@@ -102,7 +107,8 @@ suspend fun TelegramBot.handleLiveLocation(
disableNotification: Boolean = false, disableNotification: Boolean = false,
protectContent: Boolean = false, protectContent: Boolean = false,
replyToMessageId: MessageId? = null, replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null allowSendingWithoutReply: Boolean? = null,
sentMessageFlow: FlowCollector<ContentMessage<LocationContent>>? = null
) { ) {
handleLiveLocation( handleLiveLocation(
chatId, chatId,
@@ -121,7 +127,8 @@ suspend fun TelegramBot.handleLiveLocation(
disableNotification, disableNotification,
protectContent, protectContent,
replyToMessageId, replyToMessageId,
allowSendingWithoutReply allowSendingWithoutReply,
sentMessageFlow
) )
} }
@@ -139,7 +146,8 @@ suspend fun TelegramBot.handleLiveLocation(
disableNotification: Boolean = false, disableNotification: Boolean = false,
protectContent: Boolean = false, protectContent: Boolean = false,
replyToMessageId: MessageId? = null, replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null allowSendingWithoutReply: Boolean? = null,
sentMessageFlow: FlowCollector<ContentMessage<LocationContent>>? = null
) { ) {
handleLiveLocation( handleLiveLocation(
chatId, chatId,
@@ -154,6 +162,7 @@ suspend fun TelegramBot.handleLiveLocation(
disableNotification, disableNotification,
protectContent, protectContent,
replyToMessageId, replyToMessageId,
allowSendingWithoutReply allowSendingWithoutReply,
sentMessageFlow
) )
} }

View File

@@ -2,15 +2,22 @@ package dev.inmo.tgbotapi.extensions.api
import com.soywiz.klock.DateTime import com.soywiz.klock.DateTime
import com.soywiz.klock.TimeSpan import com.soywiz.klock.TimeSpan
import dev.inmo.micro_utils.coroutines.LinkedSupervisorJob
import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions
import dev.inmo.tgbotapi.abstracts.types.WithReplyMarkup
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.api.edit.edit
import dev.inmo.tgbotapi.extensions.api.edit.location.live.editLiveLocation import dev.inmo.tgbotapi.extensions.api.edit.location.live.editLiveLocation
import dev.inmo.tgbotapi.extensions.api.edit.location.live.stopLiveLocation import dev.inmo.tgbotapi.extensions.api.edit.location.live.stopLiveLocation
import dev.inmo.tgbotapi.extensions.api.send.send
import dev.inmo.tgbotapi.extensions.api.send.sendLiveLocation
import dev.inmo.tgbotapi.requests.send.SendLiveLocation import dev.inmo.tgbotapi.requests.send.SendLiveLocation
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.chat.Chat import dev.inmo.tgbotapi.types.chat.Chat
import dev.inmo.tgbotapi.types.location.LiveLocation import dev.inmo.tgbotapi.types.location.LiveLocation
import dev.inmo.tgbotapi.types.location.Location
import dev.inmo.tgbotapi.types.location.StaticLocation import dev.inmo.tgbotapi.types.location.StaticLocation
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.Message import dev.inmo.tgbotapi.types.message.abstracts.Message
@@ -18,7 +25,15 @@ import dev.inmo.tgbotapi.types.message.content.LocationContent
import dev.inmo.tgbotapi.utils.extensions.threadIdOrNull import dev.inmo.tgbotapi.utils.extensions.threadIdOrNull
import io.ktor.utils.io.core.Closeable import io.ktor.utils.io.core.Closeable
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlin.js.JsName
import kotlin.jvm.JvmName
import kotlin.math.ceil import kotlin.math.ceil
val defaultLivePeriodDelayMillis = (livePeriodLimit.last - 60L) * 1000L val defaultLivePeriodDelayMillis = (livePeriodLimit.last - 60L) * 1000L
@@ -45,7 +60,8 @@ class LiveLocationProvider internal constructor(
private set private set
get() = field || leftUntilCloseMillis.millisecondsLong < 0L get() = field || leftUntilCloseMillis.millisecondsLong < 0L
private var message: ContentMessage<LocationContent> = initMessage var message: ContentMessage<LocationContent> = initMessage
private set
val lastLocation: LiveLocation val lastLocation: LiveLocation
get() = message.content.location as LiveLocation get() = message.content.location as LiveLocation

View File

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

View File

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

View File

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

View File

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

View File

@@ -14,27 +14,31 @@ suspend fun TelegramBot.restrictChatMember(
chatId: ChatIdentifier, chatId: ChatIdentifier,
userId: UserId, userId: UserId,
untilDate: TelegramDate? = null, untilDate: TelegramDate? = null,
permissions: ChatPermissions = ChatPermissions() permissions: ChatPermissions = ChatPermissions(),
) = execute(RestrictChatMember(chatId, userId, untilDate, permissions)) useIndependentChatPermissions: Boolean? = permissions.isGranular.takeIf { it }
) = execute(RestrictChatMember(chatId, userId, untilDate, permissions, useIndependentChatPermissions))
suspend fun TelegramBot.restrictChatMember( suspend fun TelegramBot.restrictChatMember(
chat: PublicChat, chat: PublicChat,
userId: UserId, userId: UserId,
untilDate: TelegramDate? = null, untilDate: TelegramDate? = null,
permissions: ChatPermissions = ChatPermissions() permissions: ChatPermissions = ChatPermissions(),
) = restrictChatMember(chat.id, userId, untilDate, permissions) useIndependentChatPermissions: Boolean? = permissions.isGranular.takeIf { it }
) = restrictChatMember(chat.id, userId, untilDate, permissions, useIndependentChatPermissions)
suspend fun TelegramBot.restrictChatMember( suspend fun TelegramBot.restrictChatMember(
chatId: IdChatIdentifier, chatId: IdChatIdentifier,
user: User, user: User,
untilDate: TelegramDate? = null, untilDate: TelegramDate? = null,
permissions: ChatPermissions = ChatPermissions() permissions: ChatPermissions = ChatPermissions(),
) = restrictChatMember(chatId, user.id, untilDate, permissions) useIndependentChatPermissions: Boolean? = permissions.isGranular.takeIf { it }
) = restrictChatMember(chatId, user.id, untilDate, permissions, useIndependentChatPermissions)
suspend fun TelegramBot.restrictChatMember( suspend fun TelegramBot.restrictChatMember(
chat: PublicChat, chat: PublicChat,
user: User, user: User,
untilDate: TelegramDate? = null, untilDate: TelegramDate? = null,
permissions: ChatPermissions = ChatPermissions() permissions: ChatPermissions = ChatPermissions(),
) = restrictChatMember(chat.id, user.id, untilDate, permissions) useIndependentChatPermissions: Boolean? = permissions.isGranular.takeIf { it }
) = restrictChatMember(chat.id, user.id, untilDate, permissions, useIndependentChatPermissions)

View File

@@ -8,10 +8,12 @@ import dev.inmo.tgbotapi.types.chat.PublicChat
suspend fun TelegramBot.setDefaultChatMembersPermissions( suspend fun TelegramBot.setDefaultChatMembersPermissions(
chatId: ChatIdentifier, chatId: ChatIdentifier,
permissions: ChatPermissions permissions: ChatPermissions,
) = execute(SetChatPermissions(chatId, permissions)) useIndependentChatPermissions: Boolean? = permissions.isGranular.takeIf { it }
) = execute(SetChatPermissions(chatId, permissions, useIndependentChatPermissions))
suspend fun TelegramBot.setDefaultChatMembersPermissions( suspend fun TelegramBot.setDefaultChatMembersPermissions(
chat: PublicChat, chat: PublicChat,
permissions: ChatPermissions permissions: ChatPermissions,
) = setDefaultChatMembersPermissions(chat.id, permissions) useIndependentChatPermissions: Boolean? = permissions.isGranular.takeIf { it }
) = setDefaultChatMembersPermissions(chat.id, permissions, useIndependentChatPermissions)

View File

@@ -10,13 +10,6 @@ suspend fun TelegramBot.getStickerSet(
GetStickerSet(name) GetStickerSet(name)
) )
@Deprecated("Renamed", ReplaceWith("getStickerSetOrThrow(sticker)", "dev.inmo.tgbotapi.extensions.api.get.getStickerSetOrThrow"))
suspend fun TelegramBot.getStickerSet(
sticker: Sticker
) = getStickerSet(
sticker.stickerSetName ?: error("Sticker must contains stickerSetName to be correctly used in getStickerSet method")
)
suspend fun TelegramBot.getStickerSetOrNull( suspend fun TelegramBot.getStickerSetOrNull(
sticker: Sticker sticker: Sticker
) = sticker.stickerSetName ?.let { ) = sticker.stickerSetName ?.let {

View File

@@ -685,20 +685,22 @@ suspend inline fun TelegramBot.reply(
suspend inline fun TelegramBot.replyWithSticker( suspend inline fun TelegramBot.replyWithSticker(
to: Message, to: Message,
sticker: InputFile, sticker: InputFile,
emoji: String? = null,
disableNotification: Boolean = false, disableNotification: Boolean = false,
protectContent: Boolean = false, protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
) = sendSticker(to.chat, sticker, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup) ) = sendSticker(to.chat, sticker, to.threadIdOrNull, emoji, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.reply( suspend inline fun TelegramBot.reply(
to: Message, to: Message,
sticker: Sticker, sticker: Sticker,
emoji: String? = null,
disableNotification: Boolean = false, disableNotification: Boolean = false,
protectContent: Boolean = false, protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
) = sendSticker(to.chat, sticker, to.threadIdOrNull, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup) ) = sendSticker(to.chat, sticker, to.threadIdOrNull, emoji, disableNotification, protectContent, to.messageId, allowSendingWithoutReply, replyMarkup)
// Videos // Videos

View File

@@ -761,22 +761,24 @@ suspend inline fun TelegramBot.replyWithSticker(
toMessageId: MessageId, toMessageId: MessageId,
sticker: InputFile, sticker: InputFile,
threadId: MessageThreadId? = toChatId.threadId, threadId: MessageThreadId? = toChatId.threadId,
emoji: String? = null,
disableNotification: Boolean = false, disableNotification: Boolean = false,
protectContent: Boolean = false, protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
) = sendSticker(toChatId, sticker, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup) ) = sendSticker(toChatId, sticker, threadId, emoji, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.reply( suspend inline fun TelegramBot.reply(
toChatId: IdChatIdentifier, toChatId: IdChatIdentifier,
toMessageId: MessageId, toMessageId: MessageId,
sticker: Sticker, sticker: Sticker,
threadId: MessageThreadId? = toChatId.threadId, threadId: MessageThreadId? = toChatId.threadId,
emoji: String? = null,
disableNotification: Boolean = false, disableNotification: Boolean = false,
protectContent: Boolean = false, protectContent: Boolean = false,
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
) = sendSticker(toChatId, sticker, threadId, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup) ) = sendSticker(toChatId, sticker, threadId, emoji, disableNotification, protectContent, toMessageId, allowSendingWithoutReply, replyMarkup)
// Videos // Videos

View File

@@ -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
)

View File

@@ -1111,12 +1111,13 @@ suspend fun TelegramBot.send(
chatId: ChatIdentifier, chatId: ChatIdentifier,
sticker: Sticker, sticker: Sticker,
threadId: MessageThreadId? = chatId.threadId, threadId: MessageThreadId? = chatId.threadId,
emoji: String? = null,
disableNotification: Boolean = false, disableNotification: Boolean = false,
protectContent: Boolean = false, protectContent: Boolean = false,
replyToMessageId: MessageId? = null, replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
) = sendSticker(chatId, sticker, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup) ) = sendSticker(chatId, sticker, threadId, emoji, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/** /**
* Will execute [sendSticker] request * Will execute [sendSticker] request
@@ -1127,12 +1128,13 @@ suspend fun TelegramBot.send(
chat: Chat, chat: Chat,
sticker: Sticker, sticker: Sticker,
threadId: MessageThreadId? = chat.id.threadId, threadId: MessageThreadId? = chat.id.threadId,
emoji: String? = null,
disableNotification: Boolean = false, disableNotification: Boolean = false,
protectContent: Boolean = false, protectContent: Boolean = false,
replyToMessageId: MessageId? = null, replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
) = sendSticker(chat, sticker, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup) ) = sendSticker(chat, sticker, threadId, emoji, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/** /**

View File

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

View File

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

View File

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

View File

@@ -19,13 +19,14 @@ suspend fun TelegramBot.sendSticker(
chatId: ChatIdentifier, chatId: ChatIdentifier,
sticker: InputFile, sticker: InputFile,
threadId: MessageThreadId? = chatId.threadId, threadId: MessageThreadId? = chatId.threadId,
emoji: String? = null,
disableNotification: Boolean = false, disableNotification: Boolean = false,
protectContent: Boolean = false, protectContent: Boolean = false,
replyToMessageId: MessageId? = null, replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
) = execute( ) = execute(
SendSticker(chatId, sticker, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup) SendSticker(chatId, sticker, threadId, emoji, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
) )
/** /**
@@ -36,12 +37,13 @@ suspend fun TelegramBot.sendSticker(
chat: Chat, chat: Chat,
sticker: InputFile, sticker: InputFile,
threadId: MessageThreadId? = chat.id.threadId, threadId: MessageThreadId? = chat.id.threadId,
emoji: String? = null,
disableNotification: Boolean = false, disableNotification: Boolean = false,
protectContent: Boolean = false, protectContent: Boolean = false,
replyToMessageId: MessageId? = null, replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
) = sendSticker(chat.id, sticker, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup) ) = sendSticker(chat.id, sticker, threadId, emoji, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/** /**
* @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or * @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or
@@ -51,12 +53,13 @@ suspend fun TelegramBot.sendSticker(
chatId: ChatIdentifier, chatId: ChatIdentifier,
sticker: Sticker, sticker: Sticker,
threadId: MessageThreadId? = chatId.threadId, threadId: MessageThreadId? = chatId.threadId,
emoji: String? = null,
disableNotification: Boolean = false, disableNotification: Boolean = false,
protectContent: Boolean = false, protectContent: Boolean = false,
replyToMessageId: MessageId? = null, replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
) = sendSticker(chatId, sticker.fileId, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup) ) = sendSticker(chatId, sticker.fileId, threadId, emoji, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)
/** /**
* @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or * @param replyMarkup Some of [KeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard] or
@@ -66,9 +69,10 @@ suspend fun TelegramBot.sendSticker(
chat: Chat, chat: Chat,
sticker: Sticker, sticker: Sticker,
threadId: MessageThreadId? = chat.id.threadId, threadId: MessageThreadId? = chat.id.threadId,
emoji: String? = null,
disableNotification: Boolean = false, disableNotification: Boolean = false,
protectContent: Boolean = false, protectContent: Boolean = false,
replyToMessageId: MessageId? = null, replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
) = sendSticker(chat, sticker.fileId, threadId, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup) ) = sendSticker(chat, sticker.fileId, threadId, emoji, disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup)

View File

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

View File

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

View File

@@ -1,90 +0,0 @@
package dev.inmo.tgbotapi.extensions.api.stickers
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
import dev.inmo.tgbotapi.requests.stickers.AddAnimatedStickerToSet
import dev.inmo.tgbotapi.types.chat.CommonUser
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.stickers.MaskPosition
import dev.inmo.tgbotapi.types.stickers.StickerSet
suspend fun TelegramBot.addAnimatedStickerToSet(
userId: UserId,
stickerSetName: String,
sticker: FileId,
emojis: String,
maskPosition: MaskPosition? = null
) = execute(
AddAnimatedStickerToSet(userId, stickerSetName, sticker, emojis, maskPosition)
)
suspend fun TelegramBot.addAnimatedStickerToSet(
userId: UserId,
stickerSetName: String,
sticker: MultipartFile,
emojis: String,
maskPosition: MaskPosition? = null
) = execute(
AddAnimatedStickerToSet(userId, stickerSetName, sticker, emojis, maskPosition)
)
suspend fun TelegramBot.addAnimatedStickerToSet(
user: CommonUser,
stickerSetName: String,
sticker: FileId,
emojis: String,
maskPosition: MaskPosition? = null
) = addAnimatedStickerToSet(
user.id, stickerSetName, sticker, emojis, maskPosition
)
suspend fun TelegramBot.addAnimatedStickerToSet(
user: CommonUser,
stickerSetName: String,
sticker: MultipartFile,
emojis: String,
maskPosition: MaskPosition? = null
) = addAnimatedStickerToSet(
user.id, stickerSetName, sticker, emojis, maskPosition
)
suspend fun TelegramBot.addAnimatedStickerToSet(
userId: UserId,
stickerSet: StickerSet,
sticker: FileId,
emojis: String,
maskPosition: MaskPosition? = null
) = addAnimatedStickerToSet(
userId, stickerSet.name, sticker, emojis, maskPosition
)
suspend fun TelegramBot.addAnimatedStickerToSet(
userId: UserId,
stickerSet: StickerSet,
sticker: MultipartFile,
emojis: String,
maskPosition: MaskPosition? = null
) = addAnimatedStickerToSet(
userId, stickerSet.name, sticker, emojis, maskPosition
)
suspend fun TelegramBot.addAnimatedStickerToSet(
user: CommonUser,
stickerSet: StickerSet,
sticker: FileId,
emojis: String,
maskPosition: MaskPosition? = null
) = addAnimatedStickerToSet(
user.id, stickerSet.name, sticker, emojis, maskPosition
)
suspend fun TelegramBot.addAnimatedStickerToSet(
user: CommonUser,
stickerSet: StickerSet,
sticker: MultipartFile,
emojis: String,
maskPosition: MaskPosition? = null
) = addAnimatedStickerToSet(
user.id, stickerSet.name, sticker, emojis, maskPosition
)

View File

@@ -1,90 +0,0 @@
package dev.inmo.tgbotapi.extensions.api.stickers
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
import dev.inmo.tgbotapi.requests.stickers.AddStaticStickerToSet
import dev.inmo.tgbotapi.types.chat.CommonUser
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.stickers.MaskPosition
import dev.inmo.tgbotapi.types.stickers.StickerSet
suspend fun TelegramBot.addStaticStickerToSet(
userId: UserId,
stickerSetName: String,
sticker: FileId,
emojis: String,
maskPosition: MaskPosition? = null
) = execute(
AddStaticStickerToSet(userId, stickerSetName, sticker, emojis, maskPosition)
)
suspend fun TelegramBot.addStaticStickerToSet(
userId: UserId,
stickerSetName: String,
sticker: MultipartFile,
emojis: String,
maskPosition: MaskPosition? = null
) = execute(
AddStaticStickerToSet(userId, stickerSetName, sticker, emojis, maskPosition)
)
suspend fun TelegramBot.addStaticStickerToSet(
user: CommonUser,
stickerSetName: String,
sticker: FileId,
emojis: String,
maskPosition: MaskPosition? = null
) = addStaticStickerToSet(
user.id, stickerSetName, sticker, emojis, maskPosition
)
suspend fun TelegramBot.addStaticStickerToSet(
user: CommonUser,
stickerSetName: String,
sticker: MultipartFile,
emojis: String,
maskPosition: MaskPosition? = null
) = addStaticStickerToSet(
user.id, stickerSetName, sticker, emojis, maskPosition
)
suspend fun TelegramBot.addStaticStickerToSet(
userId: UserId,
stickerSet: StickerSet,
sticker: FileId,
emojis: String,
maskPosition: MaskPosition? = null
) = addStaticStickerToSet(
userId, stickerSet.name, sticker, emojis, maskPosition
)
suspend fun TelegramBot.addStaticStickerToSet(
userId: UserId,
stickerSet: StickerSet,
sticker: MultipartFile,
emojis: String,
maskPosition: MaskPosition? = null
) = addStaticStickerToSet(
userId, stickerSet.name, sticker, emojis, maskPosition
)
suspend fun TelegramBot.addStaticStickerToSet(
user: CommonUser,
stickerSet: StickerSet,
sticker: FileId,
emojis: String,
maskPosition: MaskPosition? = null
) = addStaticStickerToSet(
user.id, stickerSet.name, sticker, emojis, maskPosition
)
suspend fun TelegramBot.addStaticStickerToSet(
user: CommonUser,
stickerSet: StickerSet,
sticker: MultipartFile,
emojis: String,
maskPosition: MaskPosition? = null
) = addStaticStickerToSet(
user.id, stickerSet.name, sticker, emojis, maskPosition
)

View File

@@ -0,0 +1,116 @@
package dev.inmo.tgbotapi.extensions.api.stickers
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.abstracts.InputFile
import dev.inmo.tgbotapi.requests.stickers.AddStickerToSet
import dev.inmo.tgbotapi.requests.stickers.InputSticker
import dev.inmo.tgbotapi.types.StickerType
import dev.inmo.tgbotapi.types.chat.CommonUser
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.stickers.MaskPosition
import dev.inmo.tgbotapi.types.stickers.StickerSet
suspend fun TelegramBot.addStickerToSet(
userId: UserId,
stickerSetName: String,
inputSticker: InputSticker
) = execute(
AddStickerToSet(userId, stickerSetName, inputSticker)
)
suspend fun TelegramBot.addStickerToSet(
userId: UserId,
stickerSet: StickerSet,
sticker: InputSticker
) = addStickerToSet(
userId,
stickerSet.name,
sticker
)
suspend fun TelegramBot.addStickerToSet(
userId: UserId,
stickerSet: StickerSet,
sticker: InputFile,
emojis: List<String>,
keywords: List<String> = emptyList()
) = addStickerToSet(
userId,
stickerSet,
when (stickerSet.stickerType) {
StickerType.CustomEmoji -> InputSticker.WithKeywords.CustomEmoji(
sticker,
emojis,
keywords
)
StickerType.Mask -> InputSticker.Mask(
sticker,
emojis
)
StickerType.Regular -> InputSticker.WithKeywords.Regular(
sticker,
emojis,
keywords
)
is StickerType.Unknown -> error("Unable to create sticker to the set with type ${stickerSet.stickerType}")
}
)
suspend fun TelegramBot.addStickerToSet(
userId: UserId,
stickerSet: StickerSet,
sticker: InputFile,
emojis: List<String>,
maskPosition: MaskPosition? = null
) = addStickerToSet(
userId,
stickerSet.name,
when (stickerSet.stickerType) {
StickerType.CustomEmoji -> InputSticker.WithKeywords.CustomEmoji(
sticker,
emojis,
emptyList()
)
StickerType.Mask -> InputSticker.Mask(
sticker,
emojis,
maskPosition
)
StickerType.Regular -> InputSticker.WithKeywords.Regular(
sticker,
emojis,
emptyList()
)
is StickerType.Unknown -> error("Unable to create sticker to the set with type ${stickerSet.stickerType}")
}
)
suspend fun TelegramBot.addStickerToSet(
user: CommonUser,
stickerSet: StickerSet,
sticker: InputSticker
) = addStickerToSet(
user.id,
stickerSet.name,
sticker
)
suspend fun TelegramBot.addStickerToSet(
user: CommonUser,
stickerSet: StickerSet,
sticker: InputFile,
emojis: List<String>,
keywords: List<String> = emptyList()
) = addStickerToSet(
user.id, stickerSet, sticker, emojis, keywords
)
suspend fun TelegramBot.addStickerToSet(
user: CommonUser,
stickerSet: StickerSet,
sticker: InputFile,
emojis: List<String>,
maskPosition: MaskPosition? = null
) = addStickerToSet(
user.id, stickerSet, sticker, emojis, maskPosition
)

View File

@@ -1,90 +0,0 @@
package dev.inmo.tgbotapi.extensions.api.stickers
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
import dev.inmo.tgbotapi.requests.stickers.AddVideoStickerToSet
import dev.inmo.tgbotapi.types.chat.CommonUser
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.stickers.MaskPosition
import dev.inmo.tgbotapi.types.stickers.StickerSet
suspend fun TelegramBot.addVideoStickerToSet(
userId: UserId,
stickerSetName: String,
sticker: FileId,
emojis: String,
maskPosition: MaskPosition? = null
) = execute(
AddVideoStickerToSet(userId, stickerSetName, sticker, emojis, maskPosition)
)
suspend fun TelegramBot.addVideoStickerToSet(
userId: UserId,
stickerSetName: String,
sticker: MultipartFile,
emojis: String,
maskPosition: MaskPosition? = null
) = execute(
AddVideoStickerToSet(userId, stickerSetName, sticker, emojis, maskPosition)
)
suspend fun TelegramBot.addVideoStickerToSet(
user: CommonUser,
stickerSetName: String,
sticker: FileId,
emojis: String,
maskPosition: MaskPosition? = null
) = addVideoStickerToSet(
user.id, stickerSetName, sticker, emojis, maskPosition
)
suspend fun TelegramBot.addVideoStickerToSet(
user: CommonUser,
stickerSetName: String,
sticker: MultipartFile,
emojis: String,
maskPosition: MaskPosition? = null
) = addVideoStickerToSet(
user.id, stickerSetName, sticker, emojis, maskPosition
)
suspend fun TelegramBot.addVideoStickerToSet(
userId: UserId,
stickerSet: StickerSet,
sticker: FileId,
emojis: String,
maskPosition: MaskPosition? = null
) = addVideoStickerToSet(
userId, stickerSet.name, sticker, emojis, maskPosition
)
suspend fun TelegramBot.addVideoStickerToSet(
userId: UserId,
stickerSet: StickerSet,
sticker: MultipartFile,
emojis: String,
maskPosition: MaskPosition? = null
) = addVideoStickerToSet(
userId, stickerSet.name, sticker, emojis, maskPosition
)
suspend fun TelegramBot.addVideoStickerToSet(
user: CommonUser,
stickerSet: StickerSet,
sticker: FileId,
emojis: String,
maskPosition: MaskPosition? = null
) = addVideoStickerToSet(
user.id, stickerSet.name, sticker, emojis, maskPosition
)
suspend fun TelegramBot.addVideoStickerToSet(
user: CommonUser,
stickerSet: StickerSet,
sticker: MultipartFile,
emojis: String,
maskPosition: MaskPosition? = null
) = addVideoStickerToSet(
user.id, stickerSet.name, sticker, emojis, maskPosition
)

View File

@@ -1,58 +0,0 @@
package dev.inmo.tgbotapi.extensions.api.stickers
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
import dev.inmo.tgbotapi.requests.stickers.CreateNewAnimatedStickerSet
import dev.inmo.tgbotapi.types.chat.CommonUser
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.stickers.MaskPosition
suspend fun TelegramBot.createNewAnimatedStickerSet(
userId: UserId,
name: String,
title: String,
sticker: FileId,
emojis: String,
containsMasks: Boolean? = null,
maskPosition: MaskPosition? = null
) = execute(
CreateNewAnimatedStickerSet(userId, name, title, sticker, emojis, containsMasks, maskPosition)
)
suspend fun TelegramBot.createNewAnimatedStickerSet(
userId: UserId,
name: String,
title: String,
sticker: MultipartFile,
emojis: String,
containsMasks: Boolean? = null,
maskPosition: MaskPosition? = null
) = execute(
CreateNewAnimatedStickerSet(userId, name, title, sticker, emojis, containsMasks, maskPosition)
)
suspend fun TelegramBot.createNewAnimatedStickerSet(
user: CommonUser,
name: String,
title: String,
sticker: FileId,
emojis: String,
containsMasks: Boolean? = null,
maskPosition: MaskPosition? = null
) = createNewAnimatedStickerSet(
user.id, name, title, sticker, emojis, containsMasks, maskPosition
)
suspend fun TelegramBot.createNewAnimatedStickerSet(
user: CommonUser,
name: String,
title: String,
sticker: MultipartFile,
emojis: String,
containsMasks: Boolean? = null,
maskPosition: MaskPosition? = null
) = createNewAnimatedStickerSet(
user.id, name, title, sticker, emojis, containsMasks, maskPosition
)

View File

@@ -1,54 +0,0 @@
package dev.inmo.tgbotapi.extensions.api.stickers
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
import dev.inmo.tgbotapi.requests.stickers.*
import dev.inmo.tgbotapi.types.chat.CommonUser
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.stickers.MaskPosition
suspend fun TelegramBot.createNewMaskAnimatedStickerSet(
userId: UserId,
name: String,
title: String,
sticker: FileId,
emojis: String,
maskPosition: MaskPosition
) = execute(
CreateNewMaskAnimatedStickerSet(userId, name, title, sticker, emojis, maskPosition)
)
suspend fun TelegramBot.createNewMaskAnimatedStickerSet(
userId: UserId,
name: String,
title: String,
sticker: MultipartFile,
emojis: String,
maskPosition: MaskPosition
) = execute(
CreateNewMaskAnimatedStickerSet(userId, name, title, sticker, emojis, maskPosition)
)
suspend fun TelegramBot.createNewMaskAnimatedStickerSet(
user: CommonUser,
name: String,
title: String,
sticker: FileId,
emojis: String,
maskPosition: MaskPosition
) = createNewMaskAnimatedStickerSet(
user.id, name, title, sticker, emojis, maskPosition
)
suspend fun TelegramBot.createNewMaskAnimatedStickerSet(
user: CommonUser,
name: String,
title: String,
sticker: MultipartFile,
emojis: String,
maskPosition: MaskPosition
) = createNewMaskAnimatedStickerSet(
user.id, name, title, sticker, emojis, maskPosition
)

View File

@@ -1,54 +0,0 @@
package dev.inmo.tgbotapi.extensions.api.stickers
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
import dev.inmo.tgbotapi.requests.stickers.*
import dev.inmo.tgbotapi.types.chat.CommonUser
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.stickers.MaskPosition
suspend fun TelegramBot.createNewMaskStickerSet(
userId: UserId,
name: String,
title: String,
sticker: FileId,
emojis: String,
maskPosition: MaskPosition
) = execute(
CreateNewMaskStickerSet(userId, name, title, sticker, emojis, maskPosition)
)
suspend fun TelegramBot.createNewMaskStickerSet(
userId: UserId,
name: String,
title: String,
sticker: MultipartFile,
emojis: String,
maskPosition: MaskPosition
) = execute(
CreateNewMaskStickerSet(userId, name, title, sticker, emojis, maskPosition)
)
suspend fun TelegramBot.createNewMaskStickerSet(
user: CommonUser,
name: String,
title: String,
sticker: FileId,
emojis: String,
maskPosition: MaskPosition
) = createNewMaskStickerSet(
user.id, name, title, sticker, emojis, maskPosition
)
suspend fun TelegramBot.createNewMaskStickerSet(
user: CommonUser,
name: String,
title: String,
sticker: MultipartFile,
emojis: String,
maskPosition: MaskPosition
) = createNewMaskStickerSet(
user.id, name, title, sticker, emojis, maskPosition
)

View File

@@ -1,54 +0,0 @@
package dev.inmo.tgbotapi.extensions.api.stickers
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
import dev.inmo.tgbotapi.requests.stickers.*
import dev.inmo.tgbotapi.types.chat.CommonUser
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.stickers.MaskPosition
suspend fun TelegramBot.createNewMaskVideoStickerSet(
userId: UserId,
name: String,
title: String,
sticker: FileId,
emojis: String,
maskPosition: MaskPosition
) = execute(
CreateNewMaskVideoStickerSet(userId, name, title, sticker, emojis, maskPosition)
)
suspend fun TelegramBot.createNewMaskVideoStickerSet(
userId: UserId,
name: String,
title: String,
sticker: MultipartFile,
emojis: String,
maskPosition: MaskPosition
) = execute(
CreateNewMaskVideoStickerSet(userId, name, title, sticker, emojis, maskPosition)
)
suspend fun TelegramBot.createNewMaskVideoStickerSet(
user: CommonUser,
name: String,
title: String,
sticker: FileId,
emojis: String,
maskPosition: MaskPosition
) = createNewMaskVideoStickerSet(
user.id, name, title, sticker, emojis, maskPosition
)
suspend fun TelegramBot.createNewMaskVideoStickerSet(
user: CommonUser,
name: String,
title: String,
sticker: MultipartFile,
emojis: String,
maskPosition: MaskPosition
) = createNewMaskVideoStickerSet(
user.id, name, title, sticker, emojis, maskPosition
)

View File

@@ -1,50 +0,0 @@
package dev.inmo.tgbotapi.extensions.api.stickers
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
import dev.inmo.tgbotapi.requests.stickers.*
import dev.inmo.tgbotapi.types.chat.CommonUser
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.stickers.MaskPosition
suspend fun TelegramBot.createNewRegularAnimatedStickerSet(
userId: UserId,
name: String,
title: String,
sticker: FileId,
emojis: String
) = execute(
CreateNewRegularAnimatedStickerSet(userId, name, title, sticker, emojis)
)
suspend fun TelegramBot.createNewRegularAnimatedStickerSet(
userId: UserId,
name: String,
title: String,
sticker: MultipartFile,
emojis: String
) = execute(
CreateNewRegularAnimatedStickerSet(userId, name, title, sticker, emojis)
)
suspend fun TelegramBot.createNewRegularAnimatedStickerSet(
user: CommonUser,
name: String,
title: String,
sticker: FileId,
emojis: String
) = createNewRegularAnimatedStickerSet(
user.id, name, title, sticker, emojis
)
suspend fun TelegramBot.createNewRegularAnimatedStickerSet(
user: CommonUser,
name: String,
title: String,
sticker: MultipartFile,
emojis: String
) = createNewRegularAnimatedStickerSet(
user.id, name, title, sticker, emojis
)

View File

@@ -1,50 +0,0 @@
package dev.inmo.tgbotapi.extensions.api.stickers
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
import dev.inmo.tgbotapi.requests.stickers.*
import dev.inmo.tgbotapi.types.chat.CommonUser
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.stickers.MaskPosition
suspend fun TelegramBot.createNewRegularStickerSet(
userId: UserId,
name: String,
title: String,
sticker: FileId,
emojis: String
) = execute(
CreateNewRegularStickerSet(userId, name, title, sticker, emojis)
)
suspend fun TelegramBot.createNewRegularStickerSet(
userId: UserId,
name: String,
title: String,
sticker: MultipartFile,
emojis: String
) = execute(
CreateNewRegularStickerSet(userId, name, title, sticker, emojis)
)
suspend fun TelegramBot.createNewRegularStickerSet(
user: CommonUser,
name: String,
title: String,
sticker: FileId,
emojis: String
) = createNewRegularStickerSet(
user.id, name, title, sticker, emojis
)
suspend fun TelegramBot.createNewRegularStickerSet(
user: CommonUser,
name: String,
title: String,
sticker: MultipartFile,
emojis: String
) = createNewRegularStickerSet(
user.id, name, title, sticker, emojis
)

View File

@@ -1,50 +0,0 @@
package dev.inmo.tgbotapi.extensions.api.stickers
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
import dev.inmo.tgbotapi.requests.stickers.*
import dev.inmo.tgbotapi.types.chat.CommonUser
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.stickers.MaskPosition
suspend fun TelegramBot.createNewRegularVideoStickerSet(
userId: UserId,
name: String,
title: String,
sticker: FileId,
emojis: String
) = execute(
CreateNewRegularVideoStickerSet(userId, name, title, sticker, emojis)
)
suspend fun TelegramBot.createNewRegularVideoStickerSet(
userId: UserId,
name: String,
title: String,
sticker: MultipartFile,
emojis: String
) = execute(
CreateNewRegularVideoStickerSet(userId, name, title, sticker, emojis)
)
suspend fun TelegramBot.createNewRegularVideoStickerSet(
user: CommonUser,
name: String,
title: String,
sticker: FileId,
emojis: String
) = createNewRegularVideoStickerSet(
user.id, name, title, sticker, emojis
)
suspend fun TelegramBot.createNewRegularVideoStickerSet(
user: CommonUser,
name: String,
title: String,
sticker: MultipartFile,
emojis: String
) = createNewRegularVideoStickerSet(
user.id, name, title, sticker, emojis
)

View File

@@ -1,58 +0,0 @@
package dev.inmo.tgbotapi.extensions.api.stickers
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
import dev.inmo.tgbotapi.requests.stickers.CreateNewStaticStickerSet
import dev.inmo.tgbotapi.types.chat.CommonUser
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.stickers.MaskPosition
suspend fun TelegramBot.createNewStaticStickerSet(
userId: UserId,
name: String,
title: String,
sticker: FileId,
emojis: String,
containsMasks: Boolean? = null,
maskPosition: MaskPosition? = null
) = execute(
CreateNewStaticStickerSet(userId, name, title, sticker, emojis, containsMasks, maskPosition)
)
suspend fun TelegramBot.createNewStaticStickerSet(
userId: UserId,
name: String,
title: String,
sticker: MultipartFile,
emojis: String,
containsMasks: Boolean? = null,
maskPosition: MaskPosition? = null
) = execute(
CreateNewStaticStickerSet(userId, name, title, sticker, emojis, containsMasks, maskPosition)
)
suspend fun TelegramBot.createNewStaticStickerSet(
user: CommonUser,
name: String,
title: String,
sticker: FileId,
emojis: String,
containsMasks: Boolean? = null,
maskPosition: MaskPosition? = null
) = createNewStaticStickerSet(
user.id, name, title, sticker, emojis, containsMasks, maskPosition
)
suspend fun TelegramBot.createNewStaticStickerSet(
user: CommonUser,
name: String,
title: String,
sticker: MultipartFile,
emojis: String,
containsMasks: Boolean? = null,
maskPosition: MaskPosition? = null
) = createNewStaticStickerSet(
user.id, name, title, sticker, emojis, containsMasks, maskPosition
)

View File

@@ -0,0 +1,31 @@
package dev.inmo.tgbotapi.extensions.api.stickers
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.stickers.CreateNewStickerSet
import dev.inmo.tgbotapi.requests.stickers.InputSticker
import dev.inmo.tgbotapi.types.StickerFormat
import dev.inmo.tgbotapi.types.chat.CommonUser
import dev.inmo.tgbotapi.types.UserId
suspend fun TelegramBot.createNewStickerSet(
userId: UserId,
name: String,
title: String,
stickersFormat: StickerFormat,
stickers: List<InputSticker>,
needsRepainting: Boolean = false
) = execute(
CreateNewStickerSet(userId, name, title, stickersFormat, stickers, needsRepainting)
)
suspend fun TelegramBot.createNewStickerSet(
user: CommonUser,
name: String,
title: String,
stickersFormat: StickerFormat,
stickers: List<InputSticker>,
needsRepainting: Boolean = false,
) = createNewStickerSet(
user.id, name, title, stickersFormat, stickers, needsRepainting
)

View File

@@ -1,58 +0,0 @@
package dev.inmo.tgbotapi.extensions.api.stickers
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
import dev.inmo.tgbotapi.requests.stickers.CreateNewVideoStickerSet
import dev.inmo.tgbotapi.types.chat.CommonUser
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.stickers.MaskPosition
suspend fun TelegramBot.createNewVideoStickerSet(
userId: UserId,
name: String,
title: String,
sticker: FileId,
emojis: String,
containsMasks: Boolean? = null,
maskPosition: MaskPosition? = null
) = execute(
CreateNewVideoStickerSet(userId, name, title, sticker, emojis, containsMasks, maskPosition)
)
suspend fun TelegramBot.createNewVideoStickerSet(
userId: UserId,
name: String,
title: String,
sticker: MultipartFile,
emojis: String,
containsMasks: Boolean? = null,
maskPosition: MaskPosition? = null
) = execute(
CreateNewVideoStickerSet(userId, name, title, sticker, emojis, containsMasks, maskPosition)
)
suspend fun TelegramBot.createNewVideoStickerSet(
user: CommonUser,
name: String,
title: String,
sticker: FileId,
emojis: String,
containsMasks: Boolean? = null,
maskPosition: MaskPosition? = null
) = createNewVideoStickerSet(
user.id, name, title, sticker, emojis, containsMasks, maskPosition
)
suspend fun TelegramBot.createNewVideoStickerSet(
user: CommonUser,
name: String,
title: String,
sticker: MultipartFile,
emojis: String,
containsMasks: Boolean? = null,
maskPosition: MaskPosition? = null
) = createNewVideoStickerSet(
user.id, name, title, sticker, emojis, containsMasks, maskPosition
)

View File

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

View File

@@ -0,0 +1,26 @@
package dev.inmo.tgbotapi.extensions.api.thumbs
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
import dev.inmo.tgbotapi.requests.stickers.SetCustomEmojiStickerSetThumbnail
import dev.inmo.tgbotapi.requests.stickers.SetStickerSetThumbnail
import dev.inmo.tgbotapi.types.CustomEmojiId
import dev.inmo.tgbotapi.types.StickerSetName
import dev.inmo.tgbotapi.types.chat.CommonUser
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.stickers.StickerSet
suspend fun TelegramBot.setCustomEmojiStickerSetThumbnail(
stickerSetName: StickerSetName,
customEmojiId: CustomEmojiId
) = execute(
SetCustomEmojiStickerSetThumbnail(stickerSetName, customEmojiId)
)
suspend fun TelegramBot.setCustomEmojiStickerSetThumbnail(
stickerSet: StickerSet,
customEmojiId: CustomEmojiId
) = setCustomEmojiStickerSetThumbnail(
stickerSet.name, customEmojiId
)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,19 +3,22 @@ package dev.inmo.tgbotapi.extensions.api.stickers
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
import dev.inmo.tgbotapi.requests.stickers.UploadStickerFile import dev.inmo.tgbotapi.requests.stickers.UploadStickerFile
import dev.inmo.tgbotapi.types.StickerFormat
import dev.inmo.tgbotapi.types.chat.CommonUser import dev.inmo.tgbotapi.types.chat.CommonUser
import dev.inmo.tgbotapi.types.UserId import dev.inmo.tgbotapi.types.UserId
suspend fun TelegramBot.uploadStickerFile( suspend fun TelegramBot.uploadStickerFile(
userId: UserId, userId: UserId,
sticker: MultipartFile sticker: MultipartFile,
stickerFormat: StickerFormat
) = execute( ) = execute(
UploadStickerFile(userId, sticker) UploadStickerFile(userId, sticker, stickerFormat)
) )
suspend fun TelegramBot.uploadStickerFile( suspend fun TelegramBot.uploadStickerFile(
user: CommonUser, user: CommonUser,
sticker: MultipartFile sticker: MultipartFile,
stickerFormat: StickerFormat
) = execute( ) = execute(
UploadStickerFile(user.id, sticker) UploadStickerFile(user.id, sticker, stickerFormat)
) )

View File

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

View File

@@ -9,6 +9,7 @@ import dev.inmo.tgbotapi.types.files.TelegramMediaFile
import dev.inmo.tgbotapi.types.message.content.MediaContent import dev.inmo.tgbotapi.types.message.content.MediaContent
import io.ktor.util.cio.use import io.ktor.util.cio.use
import io.ktor.util.cio.writeChannel import io.ktor.util.cio.writeChannel
import io.ktor.utils.io.copyAndClose
import io.ktor.utils.io.copyTo import io.ktor.utils.io.copyTo
import kotlinx.coroutines.job import kotlinx.coroutines.job
import java.io.File import java.io.File
@@ -25,7 +26,7 @@ suspend fun TelegramBot.downloadFile(
doOutsideOfCoroutine { destFile.createNewFile() } doOutsideOfCoroutine { destFile.createNewFile() }
destFile.writeChannel(coroutineContext.job).use { destFile.writeChannel(coroutineContext.job).use {
readChannel.copyTo(this) readChannel.copyAndClose(this)
} }
return destFile return destFile

View File

@@ -30,11 +30,17 @@ suspend fun TelegramBot.downloadFileToTemp(
suspend fun TelegramBot.downloadFileToTemp( suspend fun TelegramBot.downloadFileToTemp(
pathedFile: PathedFile pathedFile: PathedFile
) = downloadFileToTemp( ): File = downloadFileToTemp(
pathedFile.filePath pathedFile.filePath
).apply { ).run {
runCatching { val newFile = File(parentFile, "$nameWithoutExtension.${pathedFile.fileName.fileExtension}")
renameTo(File(parentFile, "$nameWithoutExtension.${pathedFile.fileName.fileExtension}")) val success = runCatching {
renameTo(newFile)
}.getOrElse { false }
if (success) {
newFile
} else {
this@run
} }
} }

View File

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

View File

@@ -8,6 +8,8 @@ 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.update.abstracts.Update import dev.inmo.tgbotapi.types.update.abstracts.Update
import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
import kotlinx.coroutines.* import kotlinx.coroutines.*
@@ -46,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,
@@ -54,6 +60,10 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()), statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(), presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(),
onStateHandlingErrorHandler: StateHandlingErrorHandler<T> = defaultStateHandlingErrorHandler(), onStateHandlingErrorHandler: StateHandlingErrorHandler<T> = defaultStateHandlingErrorHandler(),
timeoutSeconds: Seconds = 30,
autoDisableWebhooks: 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,
@@ -66,7 +76,7 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
).run { ).run {
this to scope.launch { this to scope.launch {
start() start()
longPolling(flowsUpdatesFilter, scope = scope) longPolling(flowsUpdatesFilter, timeoutSeconds, scope, autoDisableWebhooks, autoSkipTimeoutExceptions, mediaGroupsDebounceTimeMillis, defaultExceptionsHandler)
} }
} }
@@ -112,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
@@ -124,6 +138,10 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()), statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(), presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(),
onStateHandlingErrorHandler: StateHandlingErrorHandler<T> = defaultStateHandlingErrorHandler(), onStateHandlingErrorHandler: StateHandlingErrorHandler<T> = defaultStateHandlingErrorHandler(),
timeoutSeconds: Seconds = 30,
autoDisableWebhooks: Boolean = true,
autoSkipTimeoutExceptions: Boolean = true,
mediaGroupsDebounceTimeMillis: Long? = 1000L,
block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit> block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit>
) = FlowsUpdatesFilter().let { ) = FlowsUpdatesFilter().let {
buildBehaviourWithFSM( buildBehaviourWithFSM(
@@ -138,7 +156,12 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
start() start()
longPolling( longPolling(
flowsUpdatesFilter, flowsUpdatesFilter,
scope = scope timeoutSeconds,
scope,
autoDisableWebhooks,
autoSkipTimeoutExceptions,
mediaGroupsDebounceTimeMillis,
defaultExceptionsHandler
) )
} }
} }

View File

@@ -11,6 +11,8 @@ 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.updateshandlers.FlowsUpdatesFilter import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@@ -25,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]
@@ -42,6 +48,10 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSM(
presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(), presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(),
testServer: Boolean = false, testServer: Boolean = false,
onStateHandlingErrorHandler: StateHandlingErrorHandler<T> = defaultStateHandlingErrorHandler(), onStateHandlingErrorHandler: StateHandlingErrorHandler<T> = defaultStateHandlingErrorHandler(),
timeoutSeconds: Seconds = 30,
autoDisableWebhooks: Boolean = true,
autoSkipTimeoutExceptions: Boolean = true,
mediaGroupsDebounceTimeMillis: Long? = 1000L,
block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit> block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit>
): TelegramBot = telegramBot( ): TelegramBot = telegramBot(
token, token,
@@ -56,6 +66,10 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSM(
statesManager, statesManager,
presetHandlers, presetHandlers,
onStateHandlingErrorHandler, onStateHandlingErrorHandler,
timeoutSeconds,
autoDisableWebhooks,
autoSkipTimeoutExceptions,
mediaGroupsDebounceTimeMillis,
block block
) )
} }
@@ -64,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
* *
@@ -81,6 +99,10 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSMAndStartLongPolling(
presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(), presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(),
testServer: Boolean = false, testServer: Boolean = false,
onStateHandlingErrorHandler: StateHandlingErrorHandler<T> = defaultStateHandlingErrorHandler(), onStateHandlingErrorHandler: StateHandlingErrorHandler<T> = defaultStateHandlingErrorHandler(),
timeoutSeconds: Seconds = 30,
autoDisableWebhooks: 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(
@@ -95,6 +117,10 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSMAndStartLongPolling(
statesManager, statesManager,
presetHandlers, presetHandlers,
onStateHandlingErrorHandler, onStateHandlingErrorHandler,
timeoutSeconds,
autoDisableWebhooks,
autoSkipTimeoutExceptions,
mediaGroupsDebounceTimeMillis,
block block
) )
} }

View File

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

View File

@@ -5,6 +5,8 @@ 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.updateshandlers.FlowsUpdatesFilter import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
import kotlinx.coroutines.* import kotlinx.coroutines.*
@@ -46,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
@@ -53,6 +59,10 @@ suspend fun TelegramBot.buildBehaviour(
suspend fun TelegramBot.buildBehaviourWithLongPolling( suspend fun TelegramBot.buildBehaviourWithLongPolling(
scope: CoroutineScope = defaultCoroutineScopeProvider(), scope: CoroutineScope = defaultCoroutineScopeProvider(),
defaultExceptionsHandler: ExceptionHandler<Unit>? = null, defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
timeoutSeconds: Seconds = 30,
autoDisableWebhooks: Boolean = true,
autoSkipTimeoutExceptions: Boolean = true,
mediaGroupsDebounceTimeMillis: Long? = 1000L,
block: BehaviourContextReceiver<Unit> block: BehaviourContextReceiver<Unit>
): Job { ): Job {
val behaviourContext = buildBehaviour( val behaviourContext = buildBehaviour(
@@ -62,6 +72,10 @@ suspend fun TelegramBot.buildBehaviourWithLongPolling(
) )
return longPolling( return longPolling(
behaviourContext, behaviourContext,
scope = behaviourContext scope = behaviourContext,
timeoutSeconds = timeoutSeconds,
autoDisableWebhooks = autoDisableWebhooks,
autoSkipTimeoutExceptions = autoSkipTimeoutExceptions,
mediaGroupsDebounceTimeMillis = mediaGroupsDebounceTimeMillis
) )
} }

View File

@@ -5,6 +5,8 @@ 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.updateshandlers.FlowsUpdatesFilter import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl
import kotlinx.coroutines.* import kotlinx.coroutines.*
@@ -52,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
* *
@@ -66,6 +72,10 @@ suspend fun telegramBotWithBehaviourAndLongPolling(
builder: KtorRequestsExecutorBuilder.() -> Unit = {}, builder: KtorRequestsExecutorBuilder.() -> Unit = {},
defaultExceptionsHandler: ExceptionHandler<Unit>? = null, defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
testServer: Boolean = false, testServer: Boolean = false,
timeoutSeconds: Seconds = 30,
autoDisableWebhooks: Boolean = true,
autoSkipTimeoutExceptions: Boolean = true,
mediaGroupsDebounceTimeMillis: Long? = 1000L,
block: BehaviourContextReceiver<Unit> block: BehaviourContextReceiver<Unit>
): Pair<TelegramBot, Job> { ): Pair<TelegramBot, Job> {
return telegramBot( return telegramBot(
@@ -77,6 +87,10 @@ suspend fun telegramBotWithBehaviourAndLongPolling(
it to it.buildBehaviourWithLongPolling( it to it.buildBehaviourWithLongPolling(
scope ?: CoroutineScope(coroutineContext), scope ?: CoroutineScope(coroutineContext),
defaultExceptionsHandler, defaultExceptionsHandler,
timeoutSeconds,
autoDisableWebhooks,
autoSkipTimeoutExceptions,
mediaGroupsDebounceTimeMillis,
block block
) )
} }

View File

@@ -16,119 +16,111 @@ typealias CommonMessageToContentMapper<T> = suspend CommonMessage<T>.() -> T?
@RiskFeature(lowLevelRiskFeatureMessage) @RiskFeature(lowLevelRiskFeatureMessage)
suspend inline fun <reified O : MessageContent> BehaviourContext.waitContent( suspend inline fun <reified O : MessageContent> BehaviourContext.waitContent(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
includeMediaGroups: Boolean = true,
noinline errorFactory: NullableRequestBuilder<*> = { null } noinline errorFactory: NullableRequestBuilder<*> = { null }
): Flow<O> = waitContentMessage<O>(initRequest, includeMediaGroups, errorFactory).map { it.content } ): Flow<O> = waitContentMessage<O>(initRequest, errorFactory).map { it.content }
suspend fun BehaviourContext.waitContent( suspend fun BehaviourContext.waitAnyContent(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }, errorFactory: NullableRequestBuilder<*> = { null }
includeMediaGroups: Boolean = true ) = waitContent<MessageContent>(initRequest, errorFactory)
) = waitContent<MessageContent>(initRequest, includeMediaGroups, errorFactory)
suspend fun BehaviourContext.waitContact( suspend fun BehaviourContext.waitContact(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<ContactContent>(initRequest, false, errorFactory) ) = waitContent<ContactContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitDice( suspend fun BehaviourContext.waitDice(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<DiceContent>(initRequest, false, errorFactory) ) = waitContent<DiceContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitGame( suspend fun BehaviourContext.waitGame(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<GameContent>(initRequest, false, errorFactory) ) = waitContent<GameContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitLocation( suspend fun BehaviourContext.waitLocation(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<LocationContent>(initRequest, false, errorFactory) ) = waitContent<LocationContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitLiveLocation( suspend fun BehaviourContext.waitLiveLocation(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<LiveLocationContent>(initRequest, false, errorFactory) ) = waitContent<LiveLocationContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitStaticLocation( suspend fun BehaviourContext.waitStaticLocation(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<StaticLocationContent>(initRequest, false, errorFactory) ) = waitContent<StaticLocationContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitPoll( suspend fun BehaviourContext.waitPoll(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<PollContent>(initRequest, false, errorFactory) ) = waitContent<PollContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitText( suspend fun BehaviourContext.waitText(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<TextContent>(initRequest, false, errorFactory) ) = waitContent<TextContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitVenue( suspend fun BehaviourContext.waitVenue(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<VenueContent>(initRequest, false, errorFactory) ) = waitContent<VenueContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitAudioMediaGroupContent( suspend fun BehaviourContext.waitAudioMediaGroupContent(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }, errorFactory: NullableRequestBuilder<*> = { null },
includeMediaGroups: Boolean = true ) = waitContent<AudioMediaGroupPartContent>(initRequest, errorFactory)
) = waitContent<AudioMediaGroupPartContent>(initRequest, includeMediaGroups, errorFactory)
suspend fun BehaviourContext.waitDocumentMediaGroupContent( suspend fun BehaviourContext.waitDocumentMediaGroupContent(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }, errorFactory: NullableRequestBuilder<*> = { null }
includeMediaGroups: Boolean = true ) = waitContent<DocumentMediaGroupPartContent>(initRequest, errorFactory)
) = waitContent<DocumentMediaGroupPartContent>(initRequest, includeMediaGroups, errorFactory)
suspend fun BehaviourContext.waitMedia( suspend fun BehaviourContext.waitMedia(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }, errorFactory: NullableRequestBuilder<*> = { null }
includeMediaGroups: Boolean = false ) = waitContent<MediaContent>(initRequest, errorFactory)
) = waitContent<MediaContent>(initRequest, includeMediaGroups, errorFactory)
suspend fun BehaviourContext.waitAnyMediaGroupContent( suspend fun BehaviourContext.waitAnyMediaGroupContent(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }, errorFactory: NullableRequestBuilder<*> = { null },
includeMediaGroups: Boolean = true ) = waitContent<MediaGroupPartContent>(initRequest, errorFactory)
) = waitContent<MediaGroupPartContent>(initRequest, includeMediaGroups, errorFactory)
suspend fun BehaviourContext.waitVisualMediaGroupContent( suspend fun BehaviourContext.waitVisualMediaGroupContent(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }, errorFactory: NullableRequestBuilder<*> = { null },
includeMediaGroups: Boolean = true ) = waitContent<VisualMediaGroupPartContent>(initRequest, errorFactory)
) = waitContent<VisualMediaGroupPartContent>(initRequest, includeMediaGroups, errorFactory)
suspend fun BehaviourContext.waitTextedMediaContent( suspend fun BehaviourContext.waitTextedMediaContent(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }, errorFactory: NullableRequestBuilder<*> = { null },
includeMediaGroups: Boolean = true ) = waitContent<TextedMediaContent>(initRequest, errorFactory)
) = waitContent<TextedMediaContent>(initRequest, includeMediaGroups, errorFactory)
suspend fun BehaviourContext.waitAnimation( suspend fun BehaviourContext.waitAnimation(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<AnimationContent>(initRequest, false, errorFactory) ) = waitContent<AnimationContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitAudio( suspend fun BehaviourContext.waitAudio(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }, errorFactory: NullableRequestBuilder<*> = { null },
includeMediaGroups: Boolean = false ) = waitContent<AudioContent>(initRequest, errorFactory)
) = waitContent<AudioContent>(initRequest, includeMediaGroups, errorFactory)
suspend fun BehaviourContext.waitDocument( suspend fun BehaviourContext.waitDocument(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }, errorFactory: NullableRequestBuilder<*> = { null },
includeMediaGroups: Boolean = false ) = waitContent<DocumentContent>(initRequest, errorFactory)
) = waitContent<DocumentContent>(initRequest, includeMediaGroups, errorFactory)
suspend fun BehaviourContext.waitPhoto( suspend fun BehaviourContext.waitPhoto(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }, errorFactory: NullableRequestBuilder<*> = { null },
includeMediaGroups: Boolean = false ) = waitContent<PhotoContent>(initRequest, errorFactory)
) = waitContent<PhotoContent>(initRequest, includeMediaGroups, errorFactory)
suspend fun BehaviourContext.waitSticker( suspend fun BehaviourContext.waitSticker(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<StickerContent>(initRequest, false, errorFactory) ) = waitContent<StickerContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitVideo( suspend fun BehaviourContext.waitVideo(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }, errorFactory: NullableRequestBuilder<*> = { null }
includeMediaGroups: Boolean = false ) = waitContent<VideoContent>(initRequest, errorFactory)
) = waitContent<VideoContent>(initRequest, includeMediaGroups, errorFactory)
suspend fun BehaviourContext.waitVideoNote( suspend fun BehaviourContext.waitVideoNote(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<VideoNoteContent>(initRequest, false, errorFactory) ) = waitContent<VideoNoteContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitVoice( suspend fun BehaviourContext.waitVoice(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<VoiceContent>(initRequest, false, errorFactory) ) = waitContent<VoiceContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitInvoice( suspend fun BehaviourContext.waitInvoice(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<InvoiceContent>(initRequest, false, errorFactory) ) = waitContent<InvoiceContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitVisualContent(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContent<VisualMediaGroupPartContent>(initRequest, errorFactory)

View File

@@ -18,12 +18,14 @@ typealias CommonMessageToCommonMessageMapper<T> = suspend CommonMessage<T>.() ->
@RiskFeature(lowLevelRiskFeatureMessage) @RiskFeature(lowLevelRiskFeatureMessage)
suspend inline fun <reified O : MessageContent> BehaviourContext.waitContentMessage( suspend inline fun <reified O : MessageContent> BehaviourContext.waitContentMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
includeMediaGroups: Boolean = true,
noinline errorFactory: NullableRequestBuilder<*> = { null } noinline errorFactory: NullableRequestBuilder<*> = { null }
): Flow<CommonMessage<O>> = expectFlow( ): Flow<CommonMessage<O>> = expectFlow(
initRequest, initRequest,
errorFactory errorFactory
) { ) {
if (it !is BaseSentMessageUpdate) {
return@expectFlow emptyList()
}
listOfNotNull((it.data as? CommonMessage<*>) ?.withContent<O>()) listOfNotNull((it.data as? CommonMessage<*>) ?.withContent<O>())
} }
@@ -44,114 +46,108 @@ internal inline fun <reified T : MessageContent> contentMessageConverter(
if (content is T) this as CommonMessage<T> else null if (content is T) this as CommonMessage<T> else null
} }
suspend fun BehaviourContext.waitContentMessage( suspend fun BehaviourContext.waitAnyContentMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }, errorFactory: NullableRequestBuilder<*> = { null },
includeMediaGroups: Boolean = true ) = waitContentMessage<MessageContent>(initRequest, errorFactory)
) = waitContentMessage<MessageContent>(initRequest, includeMediaGroups, errorFactory)
suspend fun BehaviourContext.waitContactMessage( suspend fun BehaviourContext.waitContactMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<ContactContent>(initRequest, false, errorFactory) ) = waitContentMessage<ContactContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitDiceMessage( suspend fun BehaviourContext.waitDiceMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<DiceContent>(initRequest, false, errorFactory) ) = waitContentMessage<DiceContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitGameMessage( suspend fun BehaviourContext.waitGameMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<GameContent>(initRequest, false, errorFactory) ) = waitContentMessage<GameContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitLocationMessage( suspend fun BehaviourContext.waitLocationMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<LocationContent>(initRequest, false, errorFactory) ) = waitContentMessage<LocationContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitLiveLocationMessage( suspend fun BehaviourContext.waitLiveLocationMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<LiveLocationContent>(initRequest, false, errorFactory) ) = waitContentMessage<LiveLocationContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitStaticLocationMessage( suspend fun BehaviourContext.waitStaticLocationMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<StaticLocationContent>(initRequest, false, errorFactory) ) = waitContentMessage<StaticLocationContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitPollMessage( suspend fun BehaviourContext.waitPollMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<PollContent>(initRequest, false, errorFactory) ) = waitContentMessage<PollContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitTextMessage( suspend fun BehaviourContext.waitTextMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<TextContent>(initRequest, false, errorFactory) ) = waitContentMessage<TextContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitVenueMessage( suspend fun BehaviourContext.waitVenueMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<VenueContent>(initRequest, false, errorFactory) ) = waitContentMessage<VenueContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitAudioMediaGroupContentMessage( suspend fun BehaviourContext.waitAudioMediaGroupContentMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }, errorFactory: NullableRequestBuilder<*> = { null }
includeMediaGroups: Boolean = true ) = waitContentMessage<AudioMediaGroupPartContent>(initRequest, errorFactory)
) = waitContentMessage<AudioMediaGroupPartContent>(initRequest, includeMediaGroups, errorFactory)
suspend fun BehaviourContext.waitDocumentMediaGroupContentMessage( suspend fun BehaviourContext.waitDocumentMediaGroupContentMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }, errorFactory: NullableRequestBuilder<*> = { null }
includeMediaGroups: Boolean = true ) = waitContentMessage<DocumentMediaGroupPartContent>(initRequest, errorFactory)
) = waitContentMessage<DocumentMediaGroupPartContent>(initRequest, includeMediaGroups, errorFactory)
suspend fun BehaviourContext.waitMediaMessage( suspend fun BehaviourContext.waitMediaMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }, errorFactory: NullableRequestBuilder<*> = { null }
includeMediaGroups: Boolean = false ) = waitContentMessage<MediaContent>(initRequest, errorFactory)
) = waitContentMessage<MediaContent>(initRequest, includeMediaGroups, errorFactory)
suspend fun BehaviourContext.waitAnyMediaGroupContentMessage( suspend fun BehaviourContext.waitAnyMediaGroupContentMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }, errorFactory: NullableRequestBuilder<*> = { null }
includeMediaGroups: Boolean = true ) = waitContentMessage<MediaGroupPartContent>(initRequest, errorFactory)
) = waitContentMessage<MediaGroupPartContent>(initRequest, includeMediaGroups, errorFactory)
suspend fun BehaviourContext.waitVisualMediaGroupContentMessage( suspend fun BehaviourContext.waitVisualMediaGroupContentMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }, errorFactory: NullableRequestBuilder<*> = { null }
includeMediaGroups: Boolean = true ) = waitContentMessage<VisualMediaGroupPartContent>(initRequest, errorFactory)
) = waitContentMessage<VisualMediaGroupPartContent>(initRequest, includeMediaGroups, errorFactory)
suspend fun BehaviourContext.waitTextedMediaContentMessage( suspend fun BehaviourContext.waitTextedMediaContentMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }, errorFactory: NullableRequestBuilder<*> = { null }
includeMediaGroups: Boolean = true ) = waitContentMessage<TextedMediaContent>(initRequest, errorFactory)
) = waitContentMessage<TextedMediaContent>(initRequest, includeMediaGroups, errorFactory)
suspend fun BehaviourContext.waitAnimationMessage( suspend fun BehaviourContext.waitAnimationMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<AnimationContent>(initRequest, false, errorFactory) ) = waitContentMessage<AnimationContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitAudioMessage( suspend fun BehaviourContext.waitAudioMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }, errorFactory: NullableRequestBuilder<*> = { null }
includeMediaGroups: Boolean = false ) = waitContentMessage<AudioContent>(initRequest, errorFactory)
) = waitContentMessage<AudioContent>(initRequest, includeMediaGroups, errorFactory)
suspend fun BehaviourContext.waitDocumentMessage( suspend fun BehaviourContext.waitDocumentMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }, errorFactory: NullableRequestBuilder<*> = { null }
includeMediaGroups: Boolean = false ) = waitContentMessage<DocumentContent>(initRequest, errorFactory)
) = waitContentMessage<DocumentContent>(initRequest, includeMediaGroups, errorFactory)
suspend fun BehaviourContext.waitPhotoMessage( suspend fun BehaviourContext.waitPhotoMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }, errorFactory: NullableRequestBuilder<*> = { null }
includeMediaGroups: Boolean = false ) = waitContentMessage<PhotoContent>(initRequest, errorFactory)
) = waitContentMessage<PhotoContent>(initRequest, includeMediaGroups, errorFactory)
suspend fun BehaviourContext.waitStickerMessage( suspend fun BehaviourContext.waitStickerMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<StickerContent>(initRequest, false, errorFactory) ) = waitContentMessage<StickerContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitVideoMessage( suspend fun BehaviourContext.waitVideoMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }, errorFactory: NullableRequestBuilder<*> = { null }
includeMediaGroups: Boolean = false ) = waitContentMessage<VideoContent>(initRequest, errorFactory)
) = waitContentMessage<VideoContent>(initRequest, includeMediaGroups, errorFactory)
suspend fun BehaviourContext.waitVideoNoteMessage( suspend fun BehaviourContext.waitVideoNoteMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<VideoNoteContent>(initRequest, false, errorFactory) ) = waitContentMessage<VideoNoteContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitVoiceMessage( suspend fun BehaviourContext.waitVoiceMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<VoiceContent>(initRequest, false, errorFactory) ) = waitContentMessage<VoiceContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitInvoiceMessage( suspend fun BehaviourContext.waitInvoiceMessage(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<InvoiceContent>(initRequest, false, errorFactory) ) = waitContentMessage<InvoiceContent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitVisualContentMessage(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitContentMessage<VisualMediaGroupPartContent>(initRequest, errorFactory)

View File

@@ -17,6 +17,9 @@ import dev.inmo.tgbotapi.types.message.ChatEvents.forum.WriteAccessAllowed
import dev.inmo.tgbotapi.types.message.ChatEvents.voice.* import dev.inmo.tgbotapi.types.message.ChatEvents.voice.*
import dev.inmo.tgbotapi.types.message.abstracts.ChatEventMessage import dev.inmo.tgbotapi.types.message.abstracts.ChatEventMessage
import dev.inmo.tgbotapi.types.message.payments.SuccessfulPaymentEvent import dev.inmo.tgbotapi.types.message.payments.SuccessfulPaymentEvent
import dev.inmo.tgbotapi.types.request.ChatShared
import dev.inmo.tgbotapi.types.request.ChatSharedRequest
import dev.inmo.tgbotapi.types.request.UserShared
import dev.inmo.tgbotapi.utils.RiskFeature import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.lowLevelRiskFeatureMessage import dev.inmo.tgbotapi.utils.lowLevelRiskFeatureMessage
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@@ -106,7 +109,7 @@ suspend fun BehaviourContext.waitGroupChatCreatedEvents(
suspend fun BehaviourContext.waitLeftChatMemberEvents( suspend fun BehaviourContext.waitLeftChatMemberEvents(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitEvents<LeftChatMember>(initRequest, errorFactory) ) = waitEvents<LeftChatMemberEvent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitNewChatPhotoEvents( suspend fun BehaviourContext.waitNewChatPhotoEvents(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
@@ -171,3 +174,18 @@ suspend fun BehaviourContext.waitWriteAccessAllowed(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitEvents<WriteAccessAllowed>(initRequest, errorFactory) ) = waitEvents<WriteAccessAllowed>(initRequest, errorFactory)
suspend fun BehaviourContext.waitChatSharedRequest(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEvents<ChatSharedRequest>(initRequest, errorFactory)
suspend fun BehaviourContext.waitUserShared(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEvents<UserShared>(initRequest, errorFactory)
suspend fun BehaviourContext.waitChatShared(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEvents<ChatShared>(initRequest, errorFactory)

View File

@@ -9,10 +9,17 @@ import dev.inmo.tgbotapi.types.message.ChatEvents.*
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.* import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.*
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicClosed import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicClosed
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicCreated import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicCreated
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicEdited
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicReopened import dev.inmo.tgbotapi.types.message.ChatEvents.forum.ForumTopicReopened
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.GeneralForumTopicHidden
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.GeneralForumTopicUnhidden
import dev.inmo.tgbotapi.types.message.ChatEvents.forum.WriteAccessAllowed
import dev.inmo.tgbotapi.types.message.ChatEvents.voice.* import dev.inmo.tgbotapi.types.message.ChatEvents.voice.*
import dev.inmo.tgbotapi.types.message.abstracts.ChatEventMessage import dev.inmo.tgbotapi.types.message.abstracts.ChatEventMessage
import dev.inmo.tgbotapi.types.message.payments.SuccessfulPaymentEvent import dev.inmo.tgbotapi.types.message.payments.SuccessfulPaymentEvent
import dev.inmo.tgbotapi.types.request.ChatShared
import dev.inmo.tgbotapi.types.request.ChatSharedRequest
import dev.inmo.tgbotapi.types.request.UserShared
import dev.inmo.tgbotapi.utils.RiskFeature import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.lowLevelRiskFeatureMessage import dev.inmo.tgbotapi.utils.lowLevelRiskFeatureMessage
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@@ -99,7 +106,7 @@ suspend fun BehaviourContext.waitGroupChatCreatedEventsMessages(
suspend fun BehaviourContext.waitLeftChatMemberEventsMessages( suspend fun BehaviourContext.waitLeftChatMemberEventsMessages(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitEventsMessages<LeftChatMember>(initRequest, errorFactory) ) = waitEventsMessages<LeftChatMemberEvent>(initRequest, errorFactory)
suspend fun BehaviourContext.waitNewChatPhotoEventsMessages( suspend fun BehaviourContext.waitNewChatPhotoEventsMessages(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
@@ -148,3 +155,34 @@ suspend fun BehaviourContext.waitForumTopicReopenedEventsMessages(
initRequest: Request<*>? = null, initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null } errorFactory: NullableRequestBuilder<*> = { null }
) = waitEventsMessages<ForumTopicReopened>(initRequest, errorFactory) ) = waitEventsMessages<ForumTopicReopened>(initRequest, errorFactory)
suspend fun BehaviourContext.waitForumTopicEditedEventsMessages(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEventsMessages<ForumTopicEdited>(initRequest, errorFactory)
suspend fun BehaviourContext.waitGeneralForumTopicHiddenEventsMessages(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEventsMessages<GeneralForumTopicHidden>(initRequest, errorFactory)
suspend fun BehaviourContext.waitGeneralForumTopicUnhiddenEventsMessages(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEventsMessages<GeneralForumTopicUnhidden>(initRequest, errorFactory)
suspend fun BehaviourContext.waitWriteAccessAllowedEventsMessages(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEventsMessages<WriteAccessAllowed>(initRequest, errorFactory)
suspend fun BehaviourContext.waitChatSharedRequestEventsMessages(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEventsMessages<ChatSharedRequest>(initRequest, errorFactory)
suspend fun BehaviourContext.waitUserSharedEventsMessages(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEventsMessages<UserShared>(initRequest, errorFactory)
suspend fun BehaviourContext.waitChatSharedEventsMessages(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null }
) = waitEventsMessages<ChatShared>(initRequest, errorFactory)

View File

@@ -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
)

View File

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

View File

@@ -1,18 +1,3 @@
/**
* @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
*/@file:Suppress("unused", "UNCHECKED_CAST")
package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling
import dev.inmo.tgbotapi.extensions.behaviour_builder.* import dev.inmo.tgbotapi.extensions.behaviour_builder.*
@@ -35,7 +20,7 @@ internal suspend inline fun <BC : BehaviourContext, reified T : MessageContent>
noinline scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<T>> noinline scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, CommonMessage<T>>
) = on(markerFactory, initialFilter, subcontextUpdatesFilter, scenarioReceiver) { ) = on(markerFactory, initialFilter, subcontextUpdatesFilter, scenarioReceiver) {
when (it) { when (it) {
is BaseEditMessageUpdate -> (it.editMessageUpdateOrNull() ?.data ?.withContent<T>()) is BaseEditMessageUpdate -> (it.data.withContent<T>())
else -> null else -> null
} ?.let(::listOfNotNull) } ?.let(::listOfNotNull)
} }

View File

@@ -23,6 +23,9 @@ import dev.inmo.tgbotapi.types.message.PrivateEventMessage
import dev.inmo.tgbotapi.types.message.abstracts.ChatEventMessage import dev.inmo.tgbotapi.types.message.abstracts.ChatEventMessage
import dev.inmo.tgbotapi.types.message.abstracts.SupergroupEventMessage import dev.inmo.tgbotapi.types.message.abstracts.SupergroupEventMessage
import dev.inmo.tgbotapi.types.message.payments.SuccessfulPaymentEvent import dev.inmo.tgbotapi.types.message.payments.SuccessfulPaymentEvent
import dev.inmo.tgbotapi.types.request.ChatShared
import dev.inmo.tgbotapi.types.request.ChatSharedRequest
import dev.inmo.tgbotapi.types.request.UserShared
import dev.inmo.tgbotapi.types.update.abstracts.Update import dev.inmo.tgbotapi.types.update.abstracts.Update
internal suspend inline fun <BC : BehaviourContext, reified T : ChatEvent> BC.onEvent( internal suspend inline fun <BC : BehaviourContext, reified T : ChatEvent> BC.onEvent(
@@ -343,10 +346,10 @@ suspend fun <BC : BehaviourContext> BC.onGroupChatCreated(
* data * data
*/ */
suspend fun <BC : BehaviourContext> BC.onLeftChatMember( suspend fun <BC : BehaviourContext> BC.onLeftChatMember(
initialFilter: SimpleFilter<ChatEventMessage<LeftChatMember>>? = null, initialFilter: SimpleFilter<ChatEventMessage<LeftChatMemberEvent>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, ChatEventMessage<LeftChatMember>, Update>? = MessageFilterByChat, subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, ChatEventMessage<LeftChatMemberEvent>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<LeftChatMember>, Any> = ByChatMessageMarkerFactory, markerFactory: MarkerFactory<in ChatEventMessage<LeftChatMemberEvent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, ChatEventMessage<LeftChatMember>> scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, ChatEventMessage<LeftChatMemberEvent>>
) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) ) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/** /**
@@ -657,3 +660,65 @@ suspend fun <BC : BehaviourContext> BC.onWriteAccessAllowed(
markerFactory: MarkerFactory<in ChatEventMessage<WriteAccessAllowed>, Any> = ByChatMessageMarkerFactory, markerFactory: MarkerFactory<in ChatEventMessage<WriteAccessAllowed>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, SupergroupEventMessage<WriteAccessAllowed>> scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, SupergroupEventMessage<WriteAccessAllowed>>
) = onEventWithCustomChatEventMessage(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver) ) = onEventWithCustomChatEventMessage(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param markerFactory Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun <BC : BehaviourContext> BC.onChatSharedRequest(
initialFilter: SimpleFilter<PrivateEventMessage<ChatSharedRequest>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, PrivateEventMessage<ChatSharedRequest>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<ChatSharedRequest>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, PrivateEventMessage<ChatSharedRequest>>
) = onEventWithCustomChatEventMessage(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param markerFactory Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun <BC : BehaviourContext> BC.onUserShared(
initialFilter: SimpleFilter<PrivateEventMessage<UserShared>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, PrivateEventMessage<UserShared>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<UserShared>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, PrivateEventMessage<UserShared>>
) = onEventWithCustomChatEventMessage(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param markerFactory Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun <BC : BehaviourContext> BC.onChatShared(
initialFilter: SimpleFilter<PrivateEventMessage<ChatShared>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, PrivateEventMessage<ChatShared>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<ChatShared>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, PrivateEventMessage<ChatShared>>
) = onEventWithCustomChatEventMessage(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)

View File

@@ -2,6 +2,7 @@ plugins {
id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization" id "org.jetbrains.kotlin.plugin.serialization"
id "com.google.devtools.ksp" id "com.google.devtools.ksp"
id "org.jetbrains.dokka"
} }
project.description = "Core part of tgbotapi with all (and only) required functionality for working with Telegram Bot API" project.description = "Core part of tgbotapi with all (and only) required functionality for working with Telegram Bot API"
@@ -25,6 +26,7 @@ kotlin {
api libs.microutils.serialization.base64 api libs.microutils.serialization.base64
api libs.microutils.serialization.encapsulator api libs.microutils.serialization.encapsulator
api libs.microutils.serialization.typedSerializer api libs.microutils.serialization.typedSerializer
api libs.microutils.serialization.mapper
api libs.microutils.ktor.common api libs.microutils.ktor.common
api libs.microutils.languageCodes api libs.microutils.languageCodes

View File

@@ -36,8 +36,10 @@ sealed class InputFile {
} }
} }
internal const val attachPrefix = "attach://"
internal inline val InputFile.attachFileId internal inline val InputFile.attachFileId
get() = "attach://$fileId" get() = "$attachPrefix$fileId"
internal inline val InputFile.fileIdToSend internal inline val InputFile.fileIdToSend
get() = when (this) { get() = when (this) {
is FileId -> fileId is FileId -> fileId
@@ -60,8 +62,8 @@ fun String.toInputFile() = FileId(this)
@RiskFeature @RiskFeature
object InputFileSerializer : KSerializer<InputFile> { object InputFileSerializer : KSerializer<InputFile> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor(FileId::class.toString(), PrimitiveKind.STRING) override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor(FileId::class.toString(), PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: InputFile) = encoder.encodeString(value.fileId) override fun serialize(encoder: Encoder, value: InputFile) = encoder.encodeString(value.fileIdToSend)
override fun deserialize(decoder: Decoder): FileId = FileId(decoder.decodeString()) override fun deserialize(decoder: Decoder): FileId = FileId(decoder.decodeString().removePrefix(attachPrefix))
} }
// TODO:: add checks for files size // TODO:: add checks for files size

View File

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

View File

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

View File

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

View File

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

View File

@@ -16,7 +16,9 @@ data class RestrictChatMember(
@SerialName(untilDateField) @SerialName(untilDateField)
override val untilDate: TelegramDate? = null, override val untilDate: TelegramDate? = null,
@SerialName(permissionsField) @SerialName(permissionsField)
val permissions: ChatPermissions = ChatPermissions() val permissions: ChatPermissions = ChatPermissions(),
@SerialName(useIndependentChatPermissionsField)
val useIndependentChatPermissions: Boolean? = permissions.isGranular.takeIf { it }
) : ChatMemberRequest<Boolean>, UntilDate { ) : ChatMemberRequest<Boolean>, UntilDate {
override fun method(): String = "restrictChatMember" override fun method(): String = "restrictChatMember"
override val resultDeserializer: DeserializationStrategy<Boolean> override val resultDeserializer: DeserializationStrategy<Boolean>

View File

@@ -12,7 +12,9 @@ data class SetChatPermissions (
@SerialName(chatIdField) @SerialName(chatIdField)
override val chatId: ChatIdentifier, override val chatId: ChatIdentifier,
@SerialName(permissionsField) @SerialName(permissionsField)
val permissions: ChatPermissions val permissions: ChatPermissions,
@SerialName(useIndependentChatPermissionsField)
val useIndependentChatPermissions: Boolean? = permissions.isGranular.takeIf { it }
): ChatRequest, SimpleRequest<Boolean> { ): ChatRequest, SimpleRequest<Boolean> {
override fun method(): String = "setChatPermissions" override fun method(): String = "setChatPermissions"
override val resultDeserializer: DeserializationStrategy<Boolean> override val resultDeserializer: DeserializationStrategy<Boolean>

View File

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

View File

@@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.requests.send.media package dev.inmo.tgbotapi.requests.send.media
import dev.inmo.tgbotapi.requests.abstracts.* import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest
import dev.inmo.tgbotapi.requests.send.abstracts.* import dev.inmo.tgbotapi.requests.send.abstracts.*
import dev.inmo.tgbotapi.requests.send.media.base.* import dev.inmo.tgbotapi.requests.send.media.base.*
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
@@ -22,7 +23,7 @@ import kotlinx.serialization.*
fun SendAnimation( fun SendAnimation(
chatId: ChatIdentifier, chatId: ChatIdentifier,
animation: InputFile, animation: InputFile,
thumb: InputFile? = null, thumbnail: InputFile? = null,
text: String? = null, text: String? = null,
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
spoilered: Boolean = false, spoilered: Boolean = false,
@@ -36,15 +37,13 @@ fun SendAnimation(
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
): Request<ContentMessage<AnimationContent>> { ): Request<ContentMessage<AnimationContent>> {
val animationAsFileId = (animation as? FileId) ?.fileId
val animationAsFile = animation as? MultipartFile val animationAsFile = animation as? MultipartFile
val thumbAsFileId = (thumb as? FileId) ?.fileId val thumbAsFile = thumbnail as? MultipartFile
val thumbAsFile = thumb as? MultipartFile
val data = SendAnimationData( val data = SendAnimationData(
chatId, chatId,
animationAsFileId, animation,
thumbAsFileId, thumbnail ?.fileId,
text, text,
parseMode, parseMode,
null, null,
@@ -63,9 +62,9 @@ fun SendAnimation(
return if (animationAsFile == null && thumbAsFile == null) { return if (animationAsFile == null && thumbAsFile == null) {
data data
} else { } else {
MultipartRequestImpl( CommonMultipartFileRequest(
data, data,
SendAnimationFiles(animationAsFile, thumbAsFile) listOfNotNull(animationAsFile, thumbAsFile).associateBy { it.fileId }
) )
} }
} }
@@ -73,7 +72,7 @@ fun SendAnimation(
fun SendAnimation( fun SendAnimation(
chatId: ChatIdentifier, chatId: ChatIdentifier,
animation: InputFile, animation: InputFile,
thumb: InputFile? = null, thumbnail: InputFile? = null,
entities: TextSourcesList, entities: TextSourcesList,
spoilered: Boolean = false, spoilered: Boolean = false,
duration: Long? = null, duration: Long? = null,
@@ -86,15 +85,13 @@ fun SendAnimation(
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
): Request<ContentMessage<AnimationContent>> { ): Request<ContentMessage<AnimationContent>> {
val animationAsFileId = (animation as? FileId) ?.fileId
val animationAsFile = animation as? MultipartFile val animationAsFile = animation as? MultipartFile
val thumbAsFileId = (thumb as? FileId) ?.fileId val thumbAsFile = thumbnail as? MultipartFile
val thumbAsFile = thumb as? MultipartFile
val data = SendAnimationData( val data = SendAnimationData(
chatId, chatId,
animationAsFileId, animation,
thumbAsFileId, thumbnail ?.fileId,
entities.makeString(), entities.makeString(),
null, null,
entities.toRawMessageEntities(), entities.toRawMessageEntities(),
@@ -113,9 +110,9 @@ fun SendAnimation(
return if (animationAsFile == null && thumbAsFile == null) { return if (animationAsFile == null && thumbAsFile == null) {
data data
} else { } else {
MultipartRequestImpl( CommonMultipartFileRequest(
data, data,
SendAnimationFiles(animationAsFile, thumbAsFile) listOfNotNull(animationAsFile, thumbAsFile).associateBy { it.fileId }
) )
} }
} }
@@ -128,9 +125,9 @@ data class SendAnimationData internal constructor(
@SerialName(chatIdField) @SerialName(chatIdField)
override val chatId: ChatIdentifier, override val chatId: ChatIdentifier,
@SerialName(animationField) @SerialName(animationField)
val animation: String? = null, val animation: InputFile,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: String? = null, override val thumbnail: String? = null,
@SerialName(captionField) @SerialName(captionField)
override val text: String? = null, override val text: String? = null,
@SerialName(parseModeField) @SerialName(parseModeField)
@@ -187,8 +184,8 @@ data class SendAnimationData internal constructor(
data class SendAnimationFiles internal constructor( data class SendAnimationFiles internal constructor(
val animation: MultipartFile? = null, val animation: MultipartFile? = null,
val thumb: MultipartFile? = null val thumbnail: MultipartFile? = null
) : Files by mapOfNotNull( ) : Files by mapOfNotNull(
animationField to animation, animationField to animation,
thumbField to thumb thumbnailField to thumbnail
) )

View File

@@ -2,6 +2,7 @@ package dev.inmo.tgbotapi.requests.send.media
import dev.inmo.tgbotapi.abstracts.Performerable import dev.inmo.tgbotapi.abstracts.Performerable
import dev.inmo.tgbotapi.requests.abstracts.* import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest
import dev.inmo.tgbotapi.requests.send.abstracts.* import dev.inmo.tgbotapi.requests.send.abstracts.*
import dev.inmo.tgbotapi.requests.send.media.base.* import dev.inmo.tgbotapi.requests.send.media.base.*
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
@@ -23,7 +24,7 @@ import kotlinx.serialization.*
fun SendAudio( fun SendAudio(
chatId: ChatIdentifier, chatId: ChatIdentifier,
audio: InputFile, audio: InputFile,
thumb: InputFile? = null, thumbnail: InputFile? = null,
text: String? = null, text: String? = null,
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
duration: Long? = null, duration: Long? = null,
@@ -36,15 +37,13 @@ fun SendAudio(
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
): Request<ContentMessage<AudioContent>> { ): Request<ContentMessage<AudioContent>> {
val audioAsFileId = (audio as? FileId) ?.fileId
val audioAsFile = audio as? MultipartFile val audioAsFile = audio as? MultipartFile
val thumbAsFileId = (thumb as? FileId) ?.fileId val thumbAsFile = thumbnail as? MultipartFile
val thumbAsFile = thumb as? MultipartFile
val data = SendAudioData( val data = SendAudioData(
chatId, chatId,
audioAsFileId, audio,
thumbAsFileId, thumbnail ?.fileId,
text, text,
parseMode, parseMode,
null, null,
@@ -62,9 +61,9 @@ fun SendAudio(
return if (audioAsFile == null && thumbAsFile == null) { return if (audioAsFile == null && thumbAsFile == null) {
data data
} else { } else {
MultipartRequestImpl( CommonMultipartFileRequest(
data, data,
SendAudioFiles(audioAsFile, thumbAsFile) listOfNotNull(audioAsFile, thumbAsFile).associateBy { it.fileId }
) )
} }
} }
@@ -72,7 +71,7 @@ fun SendAudio(
fun SendAudio( fun SendAudio(
chatId: ChatIdentifier, chatId: ChatIdentifier,
audio: InputFile, audio: InputFile,
thumb: InputFile? = null, thumbnail: InputFile? = null,
entities: List<TextSource>, entities: List<TextSource>,
duration: Long? = null, duration: Long? = null,
performer: String? = null, performer: String? = null,
@@ -84,15 +83,13 @@ fun SendAudio(
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
): Request<ContentMessage<AudioContent>> { ): Request<ContentMessage<AudioContent>> {
val audioAsFileId = (audio as? FileId) ?.fileId
val audioAsFile = audio as? MultipartFile val audioAsFile = audio as? MultipartFile
val thumbAsFileId = (thumb as? FileId) ?.fileId val thumbAsFile = thumbnail as? MultipartFile
val thumbAsFile = thumb as? MultipartFile
val data = SendAudioData( val data = SendAudioData(
chatId, chatId,
audioAsFileId, audio,
thumbAsFileId, thumbnail ?.fileId,
entities.makeString(), entities.makeString(),
null, null,
entities.toRawMessageEntities(), entities.toRawMessageEntities(),
@@ -110,9 +107,9 @@ fun SendAudio(
return if (audioAsFile == null && thumbAsFile == null) { return if (audioAsFile == null && thumbAsFile == null) {
data data
} else { } else {
MultipartRequestImpl( CommonMultipartFileRequest(
data, data,
SendAudioFiles(audioAsFile, thumbAsFile) listOfNotNull(audioAsFile, thumbAsFile).associateBy { it.fileId }
) )
} }
} }
@@ -125,9 +122,9 @@ data class SendAudioData internal constructor(
@SerialName(chatIdField) @SerialName(chatIdField)
override val chatId: ChatIdentifier, override val chatId: ChatIdentifier,
@SerialName(audioField) @SerialName(audioField)
val audio: String? = null, val audio: InputFile,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: String? = null, override val thumbnail: String? = null,
@SerialName(captionField) @SerialName(captionField)
override val text: String? = null, override val text: String? = null,
@SerialName(parseModeField) @SerialName(parseModeField)
@@ -182,8 +179,8 @@ data class SendAudioData internal constructor(
data class SendAudioFiles internal constructor( data class SendAudioFiles internal constructor(
val audio: MultipartFile? = null, val audio: MultipartFile? = null,
val thumb: MultipartFile? = null val thumbnail: MultipartFile? = null
) : Files by mapOfNotNull( ) : Files by mapOfNotNull(
audioField to audio, audioField to audio,
thumbField to thumb thumbnailField to thumbnail
) )

View File

@@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.requests.send.media package dev.inmo.tgbotapi.requests.send.media
import dev.inmo.tgbotapi.requests.abstracts.* import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest
import dev.inmo.tgbotapi.requests.send.abstracts.* import dev.inmo.tgbotapi.requests.send.abstracts.*
import dev.inmo.tgbotapi.requests.send.media.base.* import dev.inmo.tgbotapi.requests.send.media.base.*
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
@@ -31,7 +32,7 @@ import kotlinx.serialization.*
fun SendDocument( fun SendDocument(
chatId: ChatIdentifier, chatId: ChatIdentifier,
document: InputFile, document: InputFile,
thumb: InputFile? = null, thumbnail: InputFile? = null,
text: String? = null, text: String? = null,
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
threadId: MessageThreadId? = chatId.threadId, threadId: MessageThreadId? = chatId.threadId,
@@ -42,15 +43,13 @@ fun SendDocument(
replyMarkup: KeyboardMarkup? = null, replyMarkup: KeyboardMarkup? = null,
disableContentTypeDetection: Boolean? = null disableContentTypeDetection: Boolean? = null
): Request<ContentMessage<DocumentContent>> { ): Request<ContentMessage<DocumentContent>> {
val documentAsFileId = (document as? FileId) ?.fileId
val documentAsFile = document as? MultipartFile val documentAsFile = document as? MultipartFile
val thumbAsFileId = (thumb as? FileId) ?.fileId val thumbAsFile = thumbnail as? MultipartFile
val thumbAsFile = thumb as? MultipartFile
val data = SendDocumentData( val data = SendDocumentData(
chatId, chatId,
documentAsFileId, document,
thumbAsFileId, thumbnail ?.fileId,
text, text,
parseMode, parseMode,
null, null,
@@ -66,9 +65,9 @@ fun SendDocument(
return if (documentAsFile == null && thumbAsFile == null) { return if (documentAsFile == null && thumbAsFile == null) {
data data
} else { } else {
MultipartRequestImpl( CommonMultipartFileRequest(
data, data,
SendDocumentFiles(documentAsFile, thumbAsFile) listOfNotNull(documentAsFile, thumbAsFile).associateBy { it.fileId }
) )
} }
} }
@@ -85,7 +84,7 @@ fun SendDocument(
fun SendDocument( fun SendDocument(
chatId: ChatIdentifier, chatId: ChatIdentifier,
document: InputFile, document: InputFile,
thumb: InputFile? = null, thumbnail: InputFile? = null,
entities: TextSourcesList, entities: TextSourcesList,
threadId: MessageThreadId? = chatId.threadId, threadId: MessageThreadId? = chatId.threadId,
disableNotification: Boolean = false, disableNotification: Boolean = false,
@@ -95,15 +94,13 @@ fun SendDocument(
replyMarkup: KeyboardMarkup? = null, replyMarkup: KeyboardMarkup? = null,
disableContentTypeDetection: Boolean? = null disableContentTypeDetection: Boolean? = null
): Request<ContentMessage<DocumentContent>> { ): Request<ContentMessage<DocumentContent>> {
val documentAsFileId = (document as? FileId) ?.fileId
val documentAsFile = document as? MultipartFile val documentAsFile = document as? MultipartFile
val thumbAsFileId = (thumb as? FileId) ?.fileId val thumbAsFile = thumbnail as? MultipartFile
val thumbAsFile = thumb as? MultipartFile
val data = SendDocumentData( val data = SendDocumentData(
chatId, chatId,
documentAsFileId, document,
thumbAsFileId, thumbnail ?.fileId,
entities.makeString(), entities.makeString(),
null, null,
entities.toRawMessageEntities(), entities.toRawMessageEntities(),
@@ -119,9 +116,9 @@ fun SendDocument(
return if (documentAsFile == null && thumbAsFile == null) { return if (documentAsFile == null && thumbAsFile == null) {
data data
} else { } else {
MultipartRequestImpl( CommonMultipartFileRequest(
data, data,
SendDocumentFiles(documentAsFile, thumbAsFile) listOfNotNull(documentAsFile, thumbAsFile).associateBy { it.fileId }
) )
} }
} }
@@ -143,9 +140,9 @@ data class SendDocumentData internal constructor(
@SerialName(chatIdField) @SerialName(chatIdField)
override val chatId: ChatIdentifier, override val chatId: ChatIdentifier,
@SerialName(documentField) @SerialName(documentField)
val document: String? = null, val document: InputFile,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: String? = null, override val thumbnail: String? = null,
@SerialName(captionField) @SerialName(captionField)
override val text: String? = null, override val text: String? = null,
@SerialName(parseModeField) @SerialName(parseModeField)
@@ -193,8 +190,8 @@ data class SendDocumentData internal constructor(
data class SendDocumentFiles internal constructor( data class SendDocumentFiles internal constructor(
val document: MultipartFile? = null, val document: MultipartFile? = null,
val thumb: MultipartFile? = null val thumbnail: MultipartFile? = null
) : Files by mapOfNotNull( ) : Files by mapOfNotNull(
documentField to document, documentField to document,
thumbField to thumb thumbnailField to thumbnail
) )

View File

@@ -2,10 +2,12 @@ package dev.inmo.tgbotapi.requests.send.media
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest
import dev.inmo.tgbotapi.requests.send.abstracts.SendMessageRequest import dev.inmo.tgbotapi.requests.send.abstracts.SendMessageRequest
import dev.inmo.tgbotapi.requests.send.media.base.* import dev.inmo.tgbotapi.requests.send.media.base.*
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.media.* import dev.inmo.tgbotapi.types.media.*
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.PossiblySentViaBotCommonMessage import dev.inmo.tgbotapi.types.message.abstracts.PossiblySentViaBotCommonMessage
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializeOnlySerializerClass import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializeOnlySerializerClass
import dev.inmo.tgbotapi.types.message.content.MediaGroupPartContent import dev.inmo.tgbotapi.types.message.content.MediaGroupPartContent
@@ -37,7 +39,7 @@ fun <T : MediaGroupPartContent> SendMediaGroup(
protectContent: Boolean = false, protectContent: Boolean = false,
replyToMessageId: MessageId? = null, replyToMessageId: MessageId? = null,
allowSendingWithoutReply: Boolean? = null allowSendingWithoutReply: Boolean? = null
): Request<PossiblySentViaBotCommonMessage<MediaGroupContent<T>>> { ): Request<ContentMessage<MediaGroupContent<T>>> {
if (media.size !in mediaCountInMediaGroup) { if (media.size !in mediaCountInMediaGroup) {
throwRangeError("Count of members in media group", mediaCountInMediaGroup, media.size) throwRangeError("Count of members in media group", mediaCountInMediaGroup, media.size)
} }
@@ -66,11 +68,11 @@ fun <T : MediaGroupPartContent> SendMediaGroup(
return (if (files.isEmpty()) { return (if (files.isEmpty()) {
data data
} else { } else {
MultipartRequestImpl( CommonMultipartFileRequest(
data, data,
SendMediaGroupFiles(files) files.associateBy { it.fileId }
) )
}) as Request<PossiblySentViaBotCommonMessage<MediaGroupContent<T>>> }) as Request<ContentMessage<MediaGroupContent<T>>>
} }
/** /**

View File

@@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.requests.send.media package dev.inmo.tgbotapi.requests.send.media
import dev.inmo.tgbotapi.requests.abstracts.* import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest
import dev.inmo.tgbotapi.requests.send.abstracts.* import dev.inmo.tgbotapi.requests.send.abstracts.*
import dev.inmo.tgbotapi.requests.send.media.base.* import dev.inmo.tgbotapi.requests.send.media.base.*
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
@@ -33,7 +34,7 @@ fun SendPhoto(
): Request<ContentMessage<PhotoContent>> { ): Request<ContentMessage<PhotoContent>> {
val data = SendPhotoData( val data = SendPhotoData(
chatId, chatId,
(photo as? FileId) ?.fileId, photo,
text, text,
parseMode, parseMode,
null, null,
@@ -45,12 +46,14 @@ fun SendPhoto(
allowSendingWithoutReply, allowSendingWithoutReply,
replyMarkup replyMarkup
) )
return data.photo ?.let { return if (photo is MultipartFile) {
CommonMultipartFileRequest(
data,
listOf(photo).associateBy { it.fileId }
)
} else {
data data
} ?: MultipartRequestImpl( }
data,
SendPhotoFiles(photo as MultipartFile)
)
} }
fun SendPhoto( fun SendPhoto(
@@ -67,7 +70,7 @@ fun SendPhoto(
): Request<ContentMessage<PhotoContent>> { ): Request<ContentMessage<PhotoContent>> {
val data = SendPhotoData( val data = SendPhotoData(
chatId, chatId,
(photo as? FileId)?.fileId, photo,
entities.makeString(), entities.makeString(),
null, null,
entities.toRawMessageEntities(), entities.toRawMessageEntities(),
@@ -79,12 +82,15 @@ fun SendPhoto(
allowSendingWithoutReply, allowSendingWithoutReply,
replyMarkup replyMarkup
) )
return data.photo ?.let {
return if (photo is MultipartFile) {
CommonMultipartFileRequest(
data,
listOf(photo).associateBy { it.fileId }
)
} else {
data data
} ?: MultipartRequestImpl( }
data,
SendPhotoFiles(photo as MultipartFile)
)
} }
private val commonResultDeserializer: DeserializationStrategy<ContentMessage<PhotoContent>> private val commonResultDeserializer: DeserializationStrategy<ContentMessage<PhotoContent>>
@@ -95,7 +101,7 @@ data class SendPhotoData internal constructor(
@SerialName(chatIdField) @SerialName(chatIdField)
override val chatId: ChatIdentifier, override val chatId: ChatIdentifier,
@SerialName(photoField) @SerialName(photoField)
val photo: String? = null, val photo: InputFile,
@SerialName(captionField) @SerialName(captionField)
override val text: String? = null, override val text: String? = null,
@SerialName(parseModeField) @SerialName(parseModeField)

View File

@@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.requests.send.media package dev.inmo.tgbotapi.requests.send.media
import dev.inmo.tgbotapi.requests.abstracts.* import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest
import dev.inmo.tgbotapi.requests.send.abstracts.ReplyingMarkupSendMessageRequest import dev.inmo.tgbotapi.requests.send.abstracts.ReplyingMarkupSendMessageRequest
import dev.inmo.tgbotapi.requests.send.abstracts.SendMessageRequest import dev.inmo.tgbotapi.requests.send.abstracts.SendMessageRequest
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
@@ -8,14 +9,19 @@ import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import dev.inmo.tgbotapi.types.message.content.StickerContent import dev.inmo.tgbotapi.types.message.content.StickerContent
import dev.inmo.tgbotapi.utils.mapOfNotNull
import dev.inmo.tgbotapi.utils.toJsonWithoutNulls import dev.inmo.tgbotapi.utils.toJsonWithoutNulls
import kotlinx.serialization.* import kotlinx.serialization.*
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put
fun SendSticker( fun SendSticker(
chatId: ChatIdentifier, chatId: ChatIdentifier,
sticker: InputFile, sticker: InputFile,
threadId: MessageThreadId? = chatId.threadId, threadId: MessageThreadId? = chatId.threadId,
emoji: String? = null,
disableNotification: Boolean = false, disableNotification: Boolean = false,
protectContent: Boolean = false, protectContent: Boolean = false,
replyToMessageId: MessageId? = null, replyToMessageId: MessageId? = null,
@@ -23,7 +29,7 @@ fun SendSticker(
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
): Request<ContentMessage<StickerContent>> = SendStickerByFileId( ): Request<ContentMessage<StickerContent>> = SendStickerByFileId(
chatId, chatId,
sticker as? FileId, sticker,
threadId, threadId,
disableNotification, disableNotification,
protectContent, protectContent,
@@ -32,7 +38,10 @@ fun SendSticker(
replyMarkup replyMarkup
).let { ).let {
when (sticker) { when (sticker) {
is MultipartFile -> SendStickerByFile(it, sticker) is MultipartFile -> CommonMultipartFileRequest(
it,
listOf(sticker).associateBy { it.fileId }
)
is FileId -> it is FileId -> it
} }
} }
@@ -45,7 +54,7 @@ data class SendStickerByFileId internal constructor(
@SerialName(chatIdField) @SerialName(chatIdField)
override val chatId: ChatIdentifier, override val chatId: ChatIdentifier,
@SerialName(stickerField) @SerialName(stickerField)
val sticker: FileId? = null, val sticker: InputFile,
@SerialName(messageThreadIdField) @SerialName(messageThreadIdField)
override val threadId: MessageThreadId? = chatId.threadId, override val threadId: MessageThreadId? = chatId.threadId,
@SerialName(disableNotificationField) @SerialName(disableNotificationField)
@@ -65,12 +74,3 @@ data class SendStickerByFileId internal constructor(
override val requestSerializer: SerializationStrategy<*> override val requestSerializer: SerializationStrategy<*>
get() = serializer() get() = serializer()
} }
data class SendStickerByFile internal constructor(
@Transient
private val sendStickerByFileId: SendStickerByFileId,
val sticker: MultipartFile
) : MultipartRequest<ContentMessage<StickerContent>>, Request<ContentMessage<StickerContent>> by sendStickerByFileId {
override val mediaMap: Map<String, MultipartFile> = mapOf(stickerField to sticker)
override val paramsJson: JsonObject = sendStickerByFileId.toJsonWithoutNulls(SendStickerByFileId.serializer())
}

View File

@@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.requests.send.media package dev.inmo.tgbotapi.requests.send.media
import dev.inmo.tgbotapi.requests.abstracts.* import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest
import dev.inmo.tgbotapi.requests.send.abstracts.* import dev.inmo.tgbotapi.requests.send.abstracts.*
import dev.inmo.tgbotapi.requests.send.media.base.* import dev.inmo.tgbotapi.requests.send.media.base.*
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
@@ -22,7 +23,7 @@ import kotlinx.serialization.*
fun SendVideo( fun SendVideo(
chatId: ChatIdentifier, chatId: ChatIdentifier,
video: InputFile, video: InputFile,
thumb: InputFile? = null, thumbnail: InputFile? = null,
text: String? = null, text: String? = null,
parseMode: ParseMode? = null, parseMode: ParseMode? = null,
spoilered: Boolean = false, spoilered: Boolean = false,
@@ -37,15 +38,13 @@ fun SendVideo(
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
): Request<ContentMessage<VideoContent>> { ): Request<ContentMessage<VideoContent>> {
val videoAsFileId = (video as? FileId) ?.fileId
val videoAsFile = video as? MultipartFile val videoAsFile = video as? MultipartFile
val thumbAsFileId = (thumb as? FileId) ?.fileId val thumbAsFile = thumbnail as? MultipartFile
val thumbAsFile = thumb as? MultipartFile
val data = SendVideoData( val data = SendVideoData(
chatId, chatId,
videoAsFileId, video,
thumbAsFileId, thumbnail ?.fileId,
text, text,
parseMode, parseMode,
null, null,
@@ -65,9 +64,9 @@ fun SendVideo(
return if (videoAsFile == null && thumbAsFile == null) { return if (videoAsFile == null && thumbAsFile == null) {
data data
} else { } else {
MultipartRequestImpl( CommonMultipartFileRequest(
data, data,
SendVideoFiles(videoAsFile, thumbAsFile) listOfNotNull(videoAsFile, thumbAsFile).associateBy { it.fileId }
) )
} }
} }
@@ -75,7 +74,7 @@ fun SendVideo(
fun SendVideo( fun SendVideo(
chatId: ChatIdentifier, chatId: ChatIdentifier,
video: InputFile, video: InputFile,
thumb: InputFile? = null, thumbnail: InputFile? = null,
entities: TextSourcesList, entities: TextSourcesList,
spoilered: Boolean = false, spoilered: Boolean = false,
duration: Long? = null, duration: Long? = null,
@@ -89,15 +88,13 @@ fun SendVideo(
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
): Request<ContentMessage<VideoContent>> { ): Request<ContentMessage<VideoContent>> {
val videoAsFileId = (video as? FileId) ?.fileId
val videoAsFile = video as? MultipartFile val videoAsFile = video as? MultipartFile
val thumbAsFileId = (thumb as? FileId) ?.fileId val thumbAsFile = thumbnail as? MultipartFile
val thumbAsFile = thumb as? MultipartFile
val data = SendVideoData( val data = SendVideoData(
chatId, chatId,
videoAsFileId, video,
thumbAsFileId, thumbnail ?.fileId,
entities.makeString(), entities.makeString(),
null, null,
entities.toRawMessageEntities(), entities.toRawMessageEntities(),
@@ -117,9 +114,9 @@ fun SendVideo(
return if (videoAsFile == null && thumbAsFile == null) { return if (videoAsFile == null && thumbAsFile == null) {
data data
} else { } else {
MultipartRequestImpl( CommonMultipartFileRequest(
data, data,
SendVideoFiles(videoAsFile, thumbAsFile) listOfNotNull(videoAsFile, thumbAsFile).associateBy { it.fileId }
) )
} }
} }
@@ -132,9 +129,9 @@ data class SendVideoData internal constructor(
@SerialName(chatIdField) @SerialName(chatIdField)
override val chatId: ChatIdentifier, override val chatId: ChatIdentifier,
@SerialName(videoField) @SerialName(videoField)
val video: String? = null, val video: InputFile,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: String? = null, override val thumbnail: String? = null,
@SerialName(captionField) @SerialName(captionField)
override val text: String? = null, override val text: String? = null,
@SerialName(parseModeField) @SerialName(parseModeField)
@@ -193,8 +190,8 @@ data class SendVideoData internal constructor(
data class SendVideoFiles internal constructor( data class SendVideoFiles internal constructor(
val video: MultipartFile? = null, val video: MultipartFile? = null,
val thumb: MultipartFile? = null val thumbnail: MultipartFile? = null
) : Files by mapOfNotNull( ) : Files by mapOfNotNull(
videoField to video, videoField to video,
thumbField to thumb thumbnailField to thumbnail
) )

View File

@@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.requests.send.media package dev.inmo.tgbotapi.requests.send.media
import dev.inmo.tgbotapi.requests.abstracts.* import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest
import dev.inmo.tgbotapi.requests.send.abstracts.* import dev.inmo.tgbotapi.requests.send.abstracts.*
import dev.inmo.tgbotapi.requests.send.media.base.* import dev.inmo.tgbotapi.requests.send.media.base.*
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
@@ -14,7 +15,7 @@ import kotlinx.serialization.*
fun SendVideoNote( fun SendVideoNote(
chatId: ChatIdentifier, chatId: ChatIdentifier,
videoNote: InputFile, videoNote: InputFile,
thumb: InputFile? = null, thumbnail: InputFile? = null,
duration: Long? = null, duration: Long? = null,
size: Int? = null, // in documentation - length (size of video side) size: Int? = null, // in documentation - length (size of video side)
threadId: MessageThreadId? = chatId.threadId, threadId: MessageThreadId? = chatId.threadId,
@@ -24,15 +25,13 @@ fun SendVideoNote(
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
): Request<ContentMessage<VideoNoteContent>> { ): Request<ContentMessage<VideoNoteContent>> {
val videoNoteAsFileId = (videoNote as? FileId) ?.fileId
val videoNoteAsFile = videoNote as? MultipartFile val videoNoteAsFile = videoNote as? MultipartFile
val thumbAsFileId = (thumb as? FileId) ?.fileId val thumbAsFile = thumbnail as? MultipartFile
val thumbAsFile = thumb as? MultipartFile
val data = SendVideoNoteData( val data = SendVideoNoteData(
chatId, chatId,
videoNoteAsFileId, videoNote,
thumbAsFileId, thumbnail ?.fileId,
duration, duration,
size, size,
threadId, threadId,
@@ -46,9 +45,9 @@ fun SendVideoNote(
return if (videoNoteAsFile == null && thumbAsFile == null) { return if (videoNoteAsFile == null && thumbAsFile == null) {
data data
} else { } else {
MultipartRequestImpl( CommonMultipartFileRequest(
data, data,
SendVideoNoteFiles(videoNoteAsFile, thumbAsFile) listOfNotNull(videoNoteAsFile, thumbAsFile).associateBy { it.fileId }
) )
} }
} }
@@ -61,9 +60,9 @@ data class SendVideoNoteData internal constructor(
@SerialName(chatIdField) @SerialName(chatIdField)
override val chatId: ChatIdentifier, override val chatId: ChatIdentifier,
@SerialName(videoNoteField) @SerialName(videoNoteField)
val videoNote: String? = null, val videoNote: InputFile,
@SerialName(thumbField) @SerialName(thumbnailField)
override val thumb: String? = null, override val thumbnail: String? = null,
@SerialName(durationField) @SerialName(durationField)
override val duration: Long? = null, override val duration: Long? = null,
@SerialName(lengthField) @SerialName(lengthField)
@@ -99,8 +98,8 @@ data class SendVideoNoteData internal constructor(
data class SendVideoNoteFiles internal constructor( data class SendVideoNoteFiles internal constructor(
val videoNote: MultipartFile? = null, val videoNote: MultipartFile? = null,
val thumb: MultipartFile? = null val thumbnail: MultipartFile? = null
) : Files by mapOfNotNull( ) : Files by mapOfNotNull(
videoNoteField to videoNote, videoNoteField to videoNote,
thumbField to thumb thumbnailField to thumbnail
) )

View File

@@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.requests.send.media package dev.inmo.tgbotapi.requests.send.media
import dev.inmo.tgbotapi.requests.abstracts.* import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest
import dev.inmo.tgbotapi.requests.send.abstracts.* import dev.inmo.tgbotapi.requests.send.abstracts.*
import dev.inmo.tgbotapi.requests.send.media.base.* import dev.inmo.tgbotapi.requests.send.media.base.*
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
@@ -32,12 +33,11 @@ fun SendVoice(
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
): Request<ContentMessage<VoiceContent>> { ): Request<ContentMessage<VoiceContent>> {
val voiceAsFileId = (voice as? FileId) ?.fileId
val voiceAsFile = voice as? MultipartFile val voiceAsFile = voice as? MultipartFile
val data = SendVoiceData( val data = SendVoiceData(
chatId, chatId,
voiceAsFileId, voice,
text, text,
parseMode, parseMode,
null, null,
@@ -53,9 +53,9 @@ fun SendVoice(
return if (voiceAsFile == null) { return if (voiceAsFile == null) {
data data
} else { } else {
MultipartRequestImpl( CommonMultipartFileRequest(
data, data,
SendVoiceFiles(voiceAsFile) listOfNotNull(voiceAsFile).associateBy { it.fileId }
) )
} }
} }
@@ -72,12 +72,11 @@ fun SendVoice(
allowSendingWithoutReply: Boolean? = null, allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null replyMarkup: KeyboardMarkup? = null
): Request<ContentMessage<VoiceContent>> { ): Request<ContentMessage<VoiceContent>> {
val voiceAsFileId = (voice as? FileId) ?.fileId
val voiceAsFile = voice as? MultipartFile val voiceAsFile = voice as? MultipartFile
val data = SendVoiceData( val data = SendVoiceData(
chatId, chatId,
voiceAsFileId, voice,
entities.makeString(), entities.makeString(),
null, null,
entities.toRawMessageEntities(), entities.toRawMessageEntities(),
@@ -93,9 +92,9 @@ fun SendVoice(
return if (voiceAsFile == null) { return if (voiceAsFile == null) {
data data
} else { } else {
MultipartRequestImpl( CommonMultipartFileRequest(
data, data,
SendVoiceFiles(voiceAsFile) listOfNotNull(voiceAsFile).associateBy { it.fileId }
) )
} }
} }
@@ -108,7 +107,7 @@ data class SendVoiceData internal constructor(
@SerialName(chatIdField) @SerialName(chatIdField)
override val chatId: ChatIdentifier, override val chatId: ChatIdentifier,
@SerialName(voiceField) @SerialName(voiceField)
val voice: String? = null, val voice: InputFile,
@SerialName(captionField) @SerialName(captionField)
override val text: String? = null, override val text: String? = null,
@SerialName(parseModeField) @SerialName(parseModeField)
@@ -156,8 +155,8 @@ data class SendVoiceData internal constructor(
data class SendVoiceFiles internal constructor( data class SendVoiceFiles internal constructor(
val voice: MultipartFile? = null, val voice: MultipartFile? = null,
val thumb: MultipartFile? = null val thumbnail: MultipartFile? = null
) : Files by mapOfNotNull( ) : Files by mapOfNotNull(
voiceField to voice, voiceField to voice,
thumbField to thumb thumbnailField to thumbnail
) )

View File

@@ -1,50 +0,0 @@
package dev.inmo.tgbotapi.requests.stickers
import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest
import dev.inmo.tgbotapi.requests.stickers.abstracts.StandardStickerSetAction
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.stickers.MaskPosition
import kotlinx.serialization.*
fun AddAnimatedStickerToSet(
userId: UserId,
stickerSetName: String,
sticker: InputFile,
emojis: String,
maskPosition: MaskPosition? = null
): Request<Boolean> {
val data = AddAnimatedStickerToSet(userId, stickerSetName, emojis, sticker as? FileId, maskPosition)
return when (sticker) {
is MultipartFile -> CommonMultipartFileRequest(
data,
mapOf(tgsStickerField to sticker)
)
is FileId -> data
}
}
@Serializable
data class AddAnimatedStickerToSet internal constructor(
@SerialName(userIdField)
override val userId: UserId,
@SerialName(nameField)
override val name: String,
@SerialName(emojisField)
override val emojis: String,
@SerialName(tgsStickerField)
val sticker: FileId? = null,
@SerialName(maskPositionField)
override val maskPosition: MaskPosition? = null
) : StandardStickerSetAction {
init {
if(emojis.isEmpty()) {
throw IllegalArgumentException("Emojis must not be empty")
}
}
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
override fun method(): String = "addStickerToSet"
}

View File

@@ -1,50 +0,0 @@
package dev.inmo.tgbotapi.requests.stickers
import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest
import dev.inmo.tgbotapi.requests.stickers.abstracts.StandardStickerSetAction
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.stickers.MaskPosition
import kotlinx.serialization.*
fun AddStaticStickerToSet(
userId: UserId,
stickerSetName: String,
sticker: InputFile,
emojis: String,
maskPosition: MaskPosition? = null
): Request<Boolean> {
val data = AddStaticStickerToSet(userId, stickerSetName, emojis, sticker as? FileId, maskPosition)
return when (sticker) {
is MultipartFile -> CommonMultipartFileRequest(
data,
mapOf(pngStickerField to sticker)
)
is FileId -> data
}
}
@Serializable
data class AddStaticStickerToSet internal constructor(
@SerialName(userIdField)
override val userId: UserId,
@SerialName(nameField)
override val name: String,
@SerialName(emojisField)
override val emojis: String,
@SerialName(pngStickerField)
val sticker: FileId? = null,
@SerialName(maskPositionField)
override val maskPosition: MaskPosition? = null
) : StandardStickerSetAction {
init {
if(emojis.isEmpty()) {
throw IllegalArgumentException("Emojis must not be empty")
}
}
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
override fun method(): String = "addStickerToSet"
}

View File

@@ -4,45 +4,32 @@ import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest
import dev.inmo.tgbotapi.requests.stickers.abstracts.StandardStickerSetAction import dev.inmo.tgbotapi.requests.stickers.abstracts.StandardStickerSetAction
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.stickers.MaskPosition
import kotlinx.serialization.* import kotlinx.serialization.*
fun AddVideoStickerToSet( fun AddStickerToSet(
userId: UserId, userId: UserId,
stickerSetName: String, stickerSetName: String,
sticker: InputFile, inputSticker: InputSticker
emojis: String,
maskPosition: MaskPosition? = null
): Request<Boolean> { ): Request<Boolean> {
val data = AddVideoStickerToSet(userId, stickerSetName, emojis, sticker as? FileId, maskPosition) val data = AddStickerToSetData(userId, stickerSetName, inputSticker)
return when (sticker) { return when (val sticker = inputSticker.sticker) {
is MultipartFile -> CommonMultipartFileRequest( is MultipartFile -> CommonMultipartFileRequest(
data, data,
mapOf(webmStickerField to sticker) mapOf(sticker.fileId to sticker)
) )
is FileId -> data is FileId -> data
} }
} }
@Serializable @Serializable
data class AddVideoStickerToSet internal constructor( data class AddStickerToSetData internal constructor(
@SerialName(userIdField) @SerialName(userIdField)
override val userId: UserId, override val userId: UserId,
@SerialName(nameField) @SerialName(nameField)
override val name: String, override val name: String,
@SerialName(emojisField) @SerialName(stickerField)
override val emojis: String, override val inputSticker: InputSticker
@SerialName(webmStickerField)
val sticker: FileId? = null,
@SerialName(maskPositionField)
override val maskPosition: MaskPosition? = null
) : StandardStickerSetAction { ) : StandardStickerSetAction {
init {
if(emojis.isEmpty()) {
throw IllegalArgumentException("Emojis must not be empty")
}
}
override val requestSerializer: SerializationStrategy<*> override val requestSerializer: SerializationStrategy<*>
get() = serializer() get() = serializer()

View File

@@ -1,40 +0,0 @@
package dev.inmo.tgbotapi.requests.stickers
import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest
import dev.inmo.tgbotapi.requests.stickers.abstracts.CreateStickerSetAction
import dev.inmo.tgbotapi.requests.stickers.abstracts.StandardStickerSetAction
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.stickers.MaskPosition
import kotlinx.serialization.*
@Serializable
@Deprecated("Use CreateNewStickerSet class instead")
data class CreateNewAnimatedStickerSet internal constructor(
@SerialName(userIdField)
override val userId: UserId,
@SerialName(nameField)
override val name: String,
@SerialName(titleField)
override val title: String,
@SerialName(emojisField)
override val emojis: String,
@SerialName(tgsStickerField)
val sticker: FileId? = null,
@SerialName(containsMasksField)
@Deprecated("Will be removed soon due to its redundancy")
val containsMasks: Boolean? = null,
@SerialName(maskPositionField)
override val maskPosition: MaskPosition? = null
) : CreateStickerSetAction {
init {
if(emojis.isEmpty()) {
throw IllegalArgumentException("Emojis must not be empty")
}
}
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
override fun method(): String = "createNewStickerSet"
}

View File

@@ -1,40 +0,0 @@
package dev.inmo.tgbotapi.requests.stickers
import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest
import dev.inmo.tgbotapi.requests.stickers.abstracts.CreateStickerSetAction
import dev.inmo.tgbotapi.requests.stickers.abstracts.StandardStickerSetAction
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.stickers.MaskPosition
import kotlinx.serialization.*
@Serializable
@Deprecated("Use CreateNewStickerSet class instead")
data class CreateNewStaticStickerSet internal constructor(
@SerialName(userIdField)
override val userId: UserId,
@SerialName(nameField)
override val name: String,
@SerialName(titleField)
override val title: String,
@SerialName(emojisField)
override val emojis: String,
@SerialName(pngStickerField)
val sticker: FileId? = null,
@SerialName(containsMasksField)
@Deprecated("Will be removed soon due to its redundancy")
val containsMasks: Boolean? = null,
@SerialName(maskPositionField)
override val maskPosition: MaskPosition? = null
) : CreateStickerSetAction {
init {
if(emojis.isEmpty()) {
throw IllegalArgumentException("Emojis must not be empty")
}
}
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
override fun method(): String = "createNewStickerSet"
}

View File

@@ -1,77 +1,186 @@
package dev.inmo.tgbotapi.requests.stickers package dev.inmo.tgbotapi.requests.stickers
import dev.inmo.micro_utils.serialization.mapper.MapperSerializer
import dev.inmo.tgbotapi.requests.abstracts.* import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest
import dev.inmo.tgbotapi.requests.stickers.abstracts.CreateStickerSetAction import dev.inmo.tgbotapi.requests.stickers.abstracts.CreateStickerSetAction
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.stickers.MaskPosition import dev.inmo.tgbotapi.types.stickers.MaskPosition
import kotlinx.serialization.* import kotlinx.serialization.*
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
internal fun CreateNewStickerSet( /**
* Will create one of [CreateNewStickerSet] types based on the first element of [stickers]
*
* @param needsRepainting Will be used only if you are creating custom emojis sticker pack (by passing [stickers] with
* type [InputSticker.WithKeywords.CustomEmoji])
*/
fun CreateNewStickerSet(
userId: UserId, userId: UserId,
name: String, name: String,
title: String, title: String,
emojis: String, stickersFormat: StickerFormat,
stickerType: StickerType = StickerType.Regular, stickers: List<InputSticker>,
pngSticker: InputFile? = null, needsRepainting: Boolean? = null
tgsSticker: InputFile? = null,
webmSticker: InputFile? = null,
maskPosition: MaskPosition? = null
): Request<Boolean> { ): Request<Boolean> {
val data = CreateNewStickerSet( val data = when(stickers.first()) {
userId, is InputSticker.Mask -> CreateNewStickerSet.Mask(userId, name, title, stickersFormat, stickers.filterIsInstance<InputSticker.Mask>())
name, is InputSticker.WithKeywords.CustomEmoji -> CreateNewStickerSet.CustomEmoji(userId, name, title, stickersFormat, stickers.filterIsInstance<InputSticker.WithKeywords.CustomEmoji>(), needsRepainting)
title, is InputSticker.WithKeywords.Regular -> CreateNewStickerSet.Regular(userId, name, title, stickersFormat, stickers.filterIsInstance<InputSticker.WithKeywords.Regular>())
emojis, }
stickerType, val multipartParts = stickers.mapNotNull {
pngSticker as? FileId, (it.sticker as? MultipartFile)
tgsSticker as? FileId, }
webmSticker as? FileId, return if (multipartParts.isNotEmpty()) {
maskPosition when (data) { // cratch for exact determining of common multipart data type
) is CreateNewStickerSet.CustomEmoji -> CommonMultipartFileRequest(
return if (pngSticker is MultipartFile || tgsSticker is MultipartFile || webmSticker is MultipartFile) { data,
CommonMultipartFileRequest( multipartParts.associateBy { it.fileId }
data, )
listOfNotNull( is CreateNewStickerSet.Mask -> CommonMultipartFileRequest(
(pngSticker as? MultipartFile) ?.let { pngStickerField to it }, data,
(tgsSticker as? MultipartFile) ?.let { tgsStickerField to it }, multipartParts.associateBy { it.fileId }
(webmSticker as? MultipartFile) ?.let { webmStickerField to it }, )
).toMap() is CreateNewStickerSet.Regular -> CommonMultipartFileRequest(
) data,
multipartParts.associateBy { it.fileId }
)
}
} else { } else {
data data
} }
} }
@Serializable @Serializable(CreateNewStickerSetSerializer::class)
data class CreateNewStickerSet internal constructor( sealed interface CreateNewStickerSet : CreateStickerSetAction {
@SerialName(userIdField) val stickerType: StickerType
override val userId: UserId, val stickers: List<InputSticker>
@SerialName(nameField) val stickersFormat: StickerFormat
override val name: String,
@SerialName(titleField)
override val title: String,
@SerialName(emojisField)
override val emojis: String,
@SerialName(stickerTypeField)
val stickerType: StickerType = StickerType.Regular,
@SerialName(pngStickerField)
val pngSticker: FileId? = null,
@SerialName(tgsStickerField)
val tgsSticker: FileId? = null,
@SerialName(webmStickerField)
val webmSticker: FileId? = null,
@SerialName(maskPositionField)
override val maskPosition: MaskPosition? = null
) : CreateStickerSetAction {
init {
if(emojis.isEmpty()) {
throw IllegalArgumentException("Emojis must not be empty")
}
}
override val requestSerializer: SerializationStrategy<*> override val requestSerializer: SerializationStrategy<*>
get() = serializer() get() = serializer()
override fun method(): String = "createNewStickerSet" override fun method(): String = "createNewStickerSet"
@Serializable
data class Regular(
@SerialName(userIdField)
override val userId: UserId,
@SerialName(nameField)
override val name: String,
@SerialName(titleField)
override val title: String,
@SerialName(stickerFormatField)
override val stickersFormat: StickerFormat,
@SerialName(stickersField)
override val stickers: List<InputSticker.WithKeywords.Regular>
) : CreateNewStickerSet {
@SerialName(stickerTypeField)
override val stickerType: StickerType
get() = StickerType.Regular
}
@Serializable
data class Mask(
@SerialName(userIdField)
override val userId: UserId,
@SerialName(nameField)
override val name: String,
@SerialName(titleField)
override val title: String,
@SerialName(stickerFormatField)
override val stickersFormat: StickerFormat,
@SerialName(stickersField)
override val stickers: List<InputSticker.Mask>
) : CreateNewStickerSet {
@SerialName(stickerTypeField)
override val stickerType: StickerType
get() = StickerType.Mask
}
@Serializable
data class CustomEmoji(
@SerialName(userIdField)
override val userId: UserId,
@SerialName(nameField)
override val name: String,
@SerialName(titleField)
override val title: String,
@SerialName(stickerFormatField)
override val stickersFormat: StickerFormat,
@SerialName(stickersField)
override val stickers: List<InputSticker.WithKeywords.CustomEmoji>,
@SerialName(needsRepaintingField)
val needsRepainting: Boolean? = null
) : CreateNewStickerSet {
@SerialName(stickerTypeField)
override val stickerType: StickerType
get() = StickerType.CustomEmoji
}
@Serializable
data class SurrogateCreateNewSticker internal constructor(
@SerialName(userIdField)
override val userId: UserId,
@SerialName(nameField)
override val name: String,
@SerialName(titleField)
override val title: String,
@SerialName(stickerFormatField)
val stickersFormat: StickerFormat,
@SerialName(stickersField)
val stickers: List<InputSticker>,
@SerialName(stickerTypeField)
val stickerType: StickerType,
@SerialName(needsRepaintingField)
val needsRepainting: Boolean? = null
) : CreateStickerSetAction {
override val requestSerializer: SerializationStrategy<*>
get() = CreateNewStickerSet.serializer()
override fun method(): String = "createNewStickerSet"
}
} }
object CreateNewStickerSetSerializer : KSerializer<CreateNewStickerSet>,
MapperSerializer<CreateNewStickerSet.SurrogateCreateNewSticker, CreateNewStickerSet>(
CreateNewStickerSet.SurrogateCreateNewSticker.serializer(),
{
CreateNewStickerSet.SurrogateCreateNewSticker(
it.userId,
it.name,
it.title,
it.stickersFormat,
it.stickers,
it.stickerType,
(it as? CreateNewStickerSet.CustomEmoji)?.needsRepainting
)
},
{
when (it.stickerType) {
StickerType.CustomEmoji -> CreateNewStickerSet.CustomEmoji(
it.userId,
it.name,
it.title,
it.stickersFormat,
it.stickers.filterIsInstance<InputSticker.WithKeywords.CustomEmoji>(),
it.needsRepainting
)
StickerType.Mask -> CreateNewStickerSet.Mask(
it.userId,
it.name,
it.title,
it.stickersFormat,
it.stickers.filterIsInstance<InputSticker.Mask>(),
)
StickerType.Regular -> CreateNewStickerSet.Regular(
it.userId,
it.name,
it.title,
it.stickersFormat,
it.stickers.filterIsInstance<InputSticker.WithKeywords.Regular>(),
)
is StickerType.Unknown -> error("Unable to create new sticker set due to error in type format: ${it.stickerType}")
}
}
)

View File

@@ -1,40 +0,0 @@
package dev.inmo.tgbotapi.requests.stickers
import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.common.CommonMultipartFileRequest
import dev.inmo.tgbotapi.requests.stickers.abstracts.CreateStickerSetAction
import dev.inmo.tgbotapi.requests.stickers.abstracts.StandardStickerSetAction
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.stickers.MaskPosition
import kotlinx.serialization.*
@Serializable
@Deprecated("Use CreateNewStickerSet class instead")
data class CreateNewVideoStickerSet internal constructor(
@SerialName(userIdField)
override val userId: UserId,
@SerialName(nameField)
override val name: String,
@SerialName(titleField)
override val title: String,
@SerialName(emojisField)
override val emojis: String,
@SerialName(webmStickerField)
val sticker: FileId? = null,
@SerialName(containsMasksField)
@Deprecated("Will be removed soon due to its redundancy")
val containsMasks: Boolean? = null,
@SerialName(maskPositionField)
override val maskPosition: MaskPosition? = null
) : CreateStickerSetAction {
init {
if(emojis.isEmpty()) {
throw IllegalArgumentException("Emojis must not be empty")
}
}
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
override fun method(): String = "createNewStickerSet"
}

View File

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

View File

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

View File

@@ -0,0 +1,122 @@
package dev.inmo.tgbotapi.requests.stickers
import dev.inmo.micro_utils.serialization.mapper.MapperSerializer
import dev.inmo.tgbotapi.requests.abstracts.InputFile
import dev.inmo.tgbotapi.types.StickerType
import dev.inmo.tgbotapi.types.emojiListField
import dev.inmo.tgbotapi.types.keywordsField
import dev.inmo.tgbotapi.types.maskPositionField
import dev.inmo.tgbotapi.types.stickerField
import dev.inmo.tgbotapi.types.stickers.MaskPosition
import dev.inmo.tgbotapi.utils.internal.ClassCastsIncluded
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@ClassCastsIncluded
@Serializable(InputStickerSerializer::class)
sealed interface InputSticker {
val sticker: InputFile
val emojisList: List<String>
@Serializable
data class Mask(
@SerialName(stickerField)
override val sticker: InputFile,
@SerialName(emojiListField)
override val emojisList: List<String>,
@SerialName(maskPositionField)
val maskPosition: MaskPosition? = null
) : InputSticker
@Serializable
sealed interface WithKeywords : InputSticker {
val keywords: List<String>
@Serializable
data class Regular(
@SerialName(stickerField)
override val sticker: InputFile,
@SerialName(emojiListField)
override val emojisList: List<String>,
@SerialName(keywordsField)
override val keywords: List<String>
) : WithKeywords
@Serializable
data class CustomEmoji(
@SerialName(stickerField)
override val sticker: InputFile,
@SerialName(emojiListField)
override val emojisList: List<String>,
@SerialName(keywordsField)
override val keywords: List<String>
) : WithKeywords
}
}
object InputStickerSerializer : KSerializer<InputSticker>, MapperSerializer<InputStickerSerializer.SurrogateInputSticker, InputSticker>(
SurrogateInputSticker.serializer(),
{
when (it) {
is InputSticker.Mask -> SurrogateInputSticker(
it.sticker,
it.emojisList,
emptyList(),
it.maskPosition,
StickerType.Mask
)
is InputSticker.WithKeywords.CustomEmoji -> SurrogateInputSticker(
it.sticker,
it.emojisList,
it.keywords,
null,
StickerType.CustomEmoji
)
is InputSticker.WithKeywords.Regular -> SurrogateInputSticker(
it.sticker,
it.emojisList,
it.keywords,
null,
StickerType.Regular
)
}
},
{
when (it.internalType) {
StickerType.CustomEmoji -> InputSticker.WithKeywords.CustomEmoji(
it.sticker,
it.emojisList,
it.keywords
)
StickerType.Mask -> InputSticker.Mask(
it.sticker,
it.emojisList,
it.maskPosition
)
StickerType.Regular -> InputSticker.WithKeywords.Regular(
it.sticker,
it.emojisList,
it.keywords
)
is StickerType.Unknown -> InputSticker.WithKeywords.Regular(
it.sticker,
it.emojisList,
it.keywords
)
}
},
) {
@Serializable
data class SurrogateInputSticker internal constructor(
@SerialName(stickerField)
val sticker: InputFile,
@SerialName(emojiListField)
val emojisList: List<String>,
@SerialName(keywordsField)
val keywords: List<String> = emptyList(),
@SerialName(maskPositionField)
val maskPosition: MaskPosition? = null,
internal val internalType: StickerType = StickerType.Unknown()
)
}

View File

@@ -1,105 +0,0 @@
package dev.inmo.tgbotapi.requests.stickers
import dev.inmo.tgbotapi.requests.abstracts.InputFile
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.types.StickerType
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.stickers.MaskPosition
fun CreateNewRegularStickerSet(
userId: UserId,
name: String,
title: String,
sticker: InputFile,
emojis: String
): Request<Boolean> = CreateNewStickerSet(
userId,
name,
title,
emojis,
StickerType.Regular,
pngSticker = sticker
)
fun CreateNewRegularVideoStickerSet(
userId: UserId,
name: String,
title: String,
sticker: InputFile,
emojis: String
): Request<Boolean> = CreateNewStickerSet(
userId,
name,
title,
emojis,
StickerType.Regular,
webmSticker = sticker
)
fun CreateNewRegularAnimatedStickerSet(
userId: UserId,
name: String,
title: String,
sticker: InputFile,
emojis: String
): Request<Boolean> = CreateNewStickerSet(
userId,
name,
title,
emojis,
StickerType.Regular,
tgsSticker = sticker
)
fun CreateNewMaskStickerSet(
userId: UserId,
name: String,
title: String,
sticker: InputFile,
emojis: String,
maskPosition: MaskPosition
): Request<Boolean> = CreateNewStickerSet(
userId,
name,
title,
emojis,
StickerType.Mask,
pngSticker = sticker,
maskPosition = maskPosition
)
fun CreateNewMaskVideoStickerSet(
userId: UserId,
name: String,
title: String,
sticker: InputFile,
emojis: String,
maskPosition: MaskPosition
): Request<Boolean> = CreateNewStickerSet(
userId,
name,
title,
emojis,
StickerType.Mask,
webmSticker = sticker,
maskPosition = maskPosition
)
fun CreateNewMaskAnimatedStickerSet(
userId: UserId,
name: String,
title: String,
sticker: InputFile,
emojis: String,
maskPosition: MaskPosition
): Request<Boolean> = CreateNewStickerSet(
userId,
name,
title,
emojis,
StickerType.Mask,
tgsSticker = sticker,
maskPosition = maskPosition
)

View File

@@ -1,80 +0,0 @@
package dev.inmo.tgbotapi.requests.stickers
import dev.inmo.tgbotapi.requests.abstracts.InputFile
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.types.StickerType
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.stickers.MaskPosition
fun CreateNewVideoStickerSet(
userId: UserId,
linkName: String,
title: String,
sticker: InputFile,
emojis: String,
containsMasks: Boolean? = null,
maskPosition: MaskPosition? = null
): Request<Boolean> = CreateNewStickerSet(
userId,
linkName,
title,
emojis,
if (containsMasks == true) StickerType.Mask else StickerType.Regular,
webmSticker = sticker,
maskPosition = maskPosition
)
fun CreateNewStaticStickerSet(
userId: UserId,
name: String,
title: String,
sticker: InputFile,
emojis: String,
containsMasks: Boolean? = null,
maskPosition: MaskPosition? = null
): Request<Boolean> = CreateNewStickerSet(
userId,
name,
title,
emojis,
if (containsMasks == true) StickerType.Mask else StickerType.Regular,
pngSticker = sticker,
maskPosition = maskPosition
)
fun CreateNewStickerSet(
userId: UserId,
name: String,
title: String,
sticker: InputFile,
emojis: String,
containsMasks: Boolean? = null,
maskPosition: MaskPosition? = null
): Request<Boolean> = CreateNewStickerSet(
userId,
name,
title,
emojis,
if (containsMasks == true) StickerType.Mask else StickerType.Regular,
pngSticker = sticker,
maskPosition = maskPosition
)
fun CreateNewAnimatedStickerSet(
userId: UserId,
name: String,
title: String,
sticker: InputFile,
emojis: String,
containsMasks: Boolean? = null,
maskPosition: MaskPosition? = null
): Request<Boolean> = CreateNewStickerSet(
userId,
name,
title,
emojis,
if (containsMasks == true) StickerType.Mask else StickerType.Regular,
tgsSticker = sticker,
maskPosition = maskPosition
)

Some files were not shown because too many files have changed in this diff Show More