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

Compare commits

...

167 Commits

Author SHA1 Message Date
913f584469 update kotlin poet 2023-05-01 02:15:27 +06:00
20278804bf potential fix of exception printing on skipping of timeout exceptions 2023-05-01 01:52:24 +06:00
631f1b9427 start 7.1.1, update dependencies and add fixes in makeLinkToMessage 2023-04-30 21:00:27 +06:00
5e0106beb5 Update README.md 2023-04-29 11:19:06 +06:00
d37e01f93e Merge pull request #748 from InsanusMokrassar/renovate/ksp
Update ksp to v1.8.21-1.0.11
2023-04-28 00:05:28 +06:00
renovate[bot]
d4492ec7ac Update ksp to v1.8.21-1.0.11 2023-04-27 17:42:32 +00:00
60d24259f4 Merge pull request #747 from InsanusMokrassar/7.1.0
7.1.0
2023-04-22 11:08:29 +06:00
8e6b3b7260 remove redundant class casts 2023-04-22 10:51:37 +06:00
e2cbd5ee0b update deprecation in old updates variables 2023-04-22 10:41:26 +06:00
1e87677ea7 Update ChatMemberUpdated.kt 2023-04-22 01:26:16 +06:00
cb3494cb39 Remove redundant chats folder invite link 2023-04-22 01:24:55 +06:00
ce81be9dcb Update UpdateTypes.kt 2023-04-22 01:10:33 +06:00
2cc02c8c85 Update UpdateTypes.kt 2023-04-22 01:05:34 +06:00
f5b2ee79d6 add info about supported tgbotapi version 2023-04-22 00:28:54 +06:00
0ba6ebb20f add editions for inline messages 2023-04-22 00:18:18 +06:00
3d2df4e255 fixes in SwitchInlineQueryChosenChat 2023-04-21 23:53:53 +06:00
33b6ff1c1e improvements in onDeepLink and waitDeepLink 2023-04-21 23:05:58 +06:00
2859f8ca2f hotfix in buttonField 2023-04-21 22:56:07 +06:00
f1aa67ceda add support of InlineQueryResultsButton 2023-04-21 22:26:11 +06:00
1c66d1e2fc add support of WriteAccessAllowed#webAppName 2023-04-21 21:47:14 +06:00
44e6d7adbc add support of SwitchInlineQueryChosenChatInlineKeyboardButton 2023-04-21 21:42:40 +06:00
61a6d4a880 add support of via_chat_folder_invite_link 2023-04-21 21:13:15 +06:00
e37237cb71 add support of get/set MyName 2023-04-21 20:51:22 +06:00
9a5a196e41 add support of custom emojies in mv2 and html 2023-04-21 20:47:13 +06:00
68f6d8553c start 7.1.0 2023-04-21 18:46:20 +06:00
6fe8e73fca Merge pull request #744 from InsanusMokrassar/7.0.2
7.0.2
2023-04-19 22:53:00 +06:00
241545c0cb fix in updates unique calculation and update dependencies 2023-04-19 20:29:40 +06:00
3b2310ece1 fixes in unique updates handling 2023-04-19 19:36:43 +06:00
e1adde0978 Update libs.versions.toml 2023-04-18 14:15:45 +06:00
3b17bce71a fix changelog and readme 2023-04-18 12:55:06 +06:00
999efc64eb complete native integration 2023-04-18 12:40:45 +06:00
05c99642cb update packages publishing to install openssl 2023-04-18 03:26:58 +06:00
cd6f4831ae MultipleClientKtorRequestsExecutor, DefaultKtorRequestsExecutor, KtorRequestsExecutor as expect class 2023-04-18 03:13:41 +06:00
2778315aed add support of fallback handlers in behaviour builder with fsm 2023-04-17 15:50:04 +06:00
ff8d67a780 potential fix in native 2023-04-13 19:26:58 +06:00
2a5f9a629d fixes in TextSourceSerializer 2023-04-13 13:58:20 +06:00
75b27858dd update dependencies 2023-04-13 12:28:51 +06:00
034e2d7ff3 Update libs.versions.toml 2023-04-04 01:43:53 +06:00
1f69c16f2a fix of build 2023-04-04 00:21:59 +06:00
8d24512413 experimentally add support of natives 2023-04-03 23:33:54 +06:00
09009003e3 start 7.0.2 2023-04-03 23:07:10 +06:00
048486146c Merge pull request #738 from InsanusMokrassar/7.0.1
7.0.1
2023-03-16 20:14:57 +06:00
b688fa570a ChatMemberUpdated now inherits WithChat and fill changes related to WithChat 2023-03-16 19:32:43 +06:00
0eba0c4e15 improvements in same-notations 2023-03-16 19:29:35 +06:00
f8bbfa2b1e Merge pull request #737 from Tolsi/more-same-flow-filters
more "same" flow filters were added
2023-03-16 18:52:13 +06:00
fec2715dc1 start 7.0.1 2023-03-16 18:48:36 +06:00
Sergey Tolmachev
941a25b116 more "same" flow filters were added 2023-03-16 16:53:39 +05:30
741d808db2 Merge pull request #736 from InsanusMokrassar/7.0.0
7.0.0
2023-03-11 22:38:33 +06:00
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
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
245 changed files with 4940 additions and 2852 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

@@ -8,12 +8,16 @@ jobs:
- uses: actions/setup-java@v1 - uses: actions/setup-java@v1
with: with:
java-version: 11 java-version: 11
- name: Setup LibCurl
run: sudo apt install -y libcurl4-openssl-dev
- name: Rewrite version - name: Rewrite version
run: | run: |
branch="`echo "${{ github.ref }}" | grep -o "[^/]*$"`" branch="`echo "${{ github.ref }}" | grep -o "[^/]*$"`"
cat gradle.properties | sed -e "s/^library_version=\([0-9\.]*\)/library_version=\1-branch_$branch-build${{ github.run_number }}/" > gradle.properties.tmp cat gradle.properties | sed -e "s/^library_version=\([0-9\.]*\)/library_version=\1-branch_$branch-build${{ github.run_number }}/" > gradle.properties.tmp
rm gradle.properties rm gradle.properties
mv gradle.properties.tmp gradle.properties mv gradle.properties.tmp gradle.properties
- name: KotlinSymbolProcessing execution
run: ./gradlew ksp
- name: Build - name: Build
run: ./gradlew build run: ./gradlew build
- name: Publish to Gitea - name: Publish to Gitea

View File

@@ -1,5 +1,141 @@
# TelegramBotAPI changelog # TelegramBotAPI changelog
## 7.1.1
* `Versions`:
* `Kotlin`: `1.8.20` -> `1.8.21`
* `MicroUtils`: `0.17.8` -> `0.18.0`
* `Utils`:
* Fixes in `makeLinkToMessage`
## 7.1.0
**This update contains changes according to the [Telegram Bot API 6.7](https://core.telegram.org/bots/api-changelog#april-21-2023)**
* `API`:
* Rename `editMessageCaption` to `editMessageMedia` due to wrong old naming
* Add `edit` extensions for `InlineMessageIdentifier`s
* `BehaviourBuilder`:
* `BehaviourContext` extensions `onDeepLink` and `waitDeepLinks` now can be used with `Regex` or `String` as first parameters
## 7.0.2
_This update brings experimental support of `linuxX64` and `mingwX64` platforms_
* `Versions`:
* `Kotlin`: `1.8.10` -> `1.8.20`
* `MicroUtils`: `0.17.5` -> `0.17.8`
* `Ktor`: `2.2.4` -> `2.3.0`
* `Core`:
* New `RequestsExecutor` - `MultipleClientKtorRequestsExecutor`
* Old `KtorRequestsExecutor` has been renamed to `DefaultKtorRequestsExecutor`
* `KtorRequestsExecutor` now is `expect class`
* On `JS`, `JVM` and `MinGWX64` platforms it is `DefaultKtorRequestsExecutor`
* On `LinuxX64` platform it is `MultipleClientKtorRequestsExecutor`
## 7.0.1
* `Core`:
* New interface `WithChat` which contains `chat` field
* `Message` now inherits `WithChat`
* `ChatMemberUpdated` now inherits `WithChat`
* `Utils`:
* Improvements in `same`-notations
## 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 ## 5.0.2
* `Versions`: * `Versions`:

View File

@@ -1,14 +1,16 @@
# 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.7-blue)](https://core.telegram.org/bots/api-changelog#april-21-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) |
| Platforms | ![JVM](https://img.shields.io/badge/JVM-red?style=plastic&logo=openjdk&logoColor=white) ![Js](https://img.shields.io/badge/JavaScript-323330?style=plastic&logo=javascript&logoColor=F7DF1E) |
| Experimental Platforms | [![Linux x64](https://img.shields.io/badge/LinuxX64-FCC624?style=plastic&logo=linux&logoColor=black)](https://kotlinlang.org/docs/native-target-support.html#tier-1) [![MinGW x64](https://img.shields.io/badge/MinGWX64-black?style=plastic&logo=windows&logoColor=green)](https://kotlinlang.org/docs/native-target-support.html#tier-1) |
<!--- [![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.2 library_version=7.1.1

View File

@@ -1,22 +1,22 @@
[versions] [versions]
kotlin = "1.7.22" kotlin = "1.8.21"
kotlin-serialization = "1.4.1" kotlin-serialization = "1.5.0"
kotlin-coroutines = "1.6.4" kotlin-coroutines = "1.6.4"
javax-activation = "1.1.1" javax-activation = "1.1.1"
korlibs = "3.4.0" korlibs = "3.4.0"
uuid = "0.6.0" uuid = "0.7.0"
ktor = "2.2.3" ktor = "2.3.0"
ksp = "1.7.22-1.0.8" ksp = "1.8.21-1.0.11"
kotlin-poet = "1.12.0" kotlin-poet = "1.13.1"
microutils = "0.16.8" microutils = "0.18.0"
github-release-plugin = "2.4.1" github-release-plugin = "2.4.1"
dokka = "1.7.20" dokka = "1.8.10"
[libraries] [libraries]
@@ -31,6 +31,8 @@ kotlin-test-js = { module = "org.jetbrains.kotlin:kotlin-test-js", version.ref =
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" } ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" } ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" }
ktor-client-curl = { module = "io.ktor:ktor-client-curl", version.ref = "ktor" }
ktor-client-winhttp = { module = "io.ktor:ktor-client-winhttp", version.ref = "ktor" }
ktor-server = { module = "io.ktor:ktor-server", version.ref = "ktor" } ktor-server = { module = "io.ktor:ktor-server", version.ref = "ktor" }
ktor-server-host-common = { module = "io.ktor:ktor-server-host-common", version.ref = "ktor" } ktor-server-host-common = { module = "io.ktor:ktor-server-host-common", version.ref = "ktor" }
@@ -45,6 +47,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 +70,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

@@ -13,6 +13,8 @@ kotlin {
browser() browser()
nodejs() nodejs()
} }
linuxX64()
mingwX64()
sourceSets { sourceSets {
commonMain { commonMain {

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

@@ -2,6 +2,7 @@ package dev.inmo.tgbotapi.extensions.api.answers
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.answers.AnswerInlineQuery import dev.inmo.tgbotapi.requests.answers.AnswerInlineQuery
import dev.inmo.tgbotapi.requests.answers.InlineQueryResultsButton
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.InlineQueryResult import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.InlineQueryResult
import dev.inmo.tgbotapi.types.InlineQueries.query.InlineQuery import dev.inmo.tgbotapi.types.InlineQueries.query.InlineQuery
import dev.inmo.tgbotapi.types.InlineQueryIdentifier import dev.inmo.tgbotapi.types.InlineQueryIdentifier
@@ -12,8 +13,37 @@ suspend fun TelegramBot.answerInlineQuery(
cachedTime: Int? = null, cachedTime: Int? = null,
isPersonal: Boolean? = null, isPersonal: Boolean? = null,
nextOffset: String? = null, nextOffset: String? = null,
switchPmText: String? = null, button: InlineQueryResultsButton? = null
switchPmParameter: String? = null ) = execute(
AnswerInlineQuery(inlineQueryID, results, cachedTime, isPersonal, nextOffset, button)
)
suspend fun TelegramBot.answerInlineQuery(
inlineQuery: InlineQuery,
results: List<InlineQueryResult> = emptyList(),
cachedTime: Int? = null,
isPersonal: Boolean? = null,
nextOffset: String? = null,
button: InlineQueryResultsButton? = null
) = answerInlineQuery(inlineQuery.id, results, cachedTime, isPersonal, nextOffset, button)
suspend fun TelegramBot.answer(
inlineQuery: InlineQuery,
results: List<InlineQueryResult> = emptyList(),
cachedTime: Int? = null,
isPersonal: Boolean? = null,
nextOffset: String? = null,
button: InlineQueryResultsButton? = null
) = answerInlineQuery(inlineQuery.id, results, cachedTime, isPersonal, nextOffset, button)
suspend fun TelegramBot.answerInlineQuery(
inlineQueryID: InlineQueryIdentifier,
results: List<InlineQueryResult> = emptyList(),
cachedTime: Int? = null,
isPersonal: Boolean? = null,
nextOffset: String? = null,
switchPmText: String?,
switchPmParameter: String?
) = execute( ) = execute(
AnswerInlineQuery(inlineQueryID, results, cachedTime, isPersonal, nextOffset, switchPmText, switchPmParameter) AnswerInlineQuery(inlineQueryID, results, cachedTime, isPersonal, nextOffset, switchPmText, switchPmParameter)
) )
@@ -24,8 +54,8 @@ suspend fun TelegramBot.answerInlineQuery(
cachedTime: Int? = null, cachedTime: Int? = null,
isPersonal: Boolean? = null, isPersonal: Boolean? = null,
nextOffset: String? = null, nextOffset: String? = null,
switchPmText: String? = null, switchPmText: String?,
switchPmParameter: String? = null switchPmParameter: String?
) = answerInlineQuery(inlineQuery.id, results, cachedTime, isPersonal, nextOffset, switchPmText, switchPmParameter) ) = answerInlineQuery(inlineQuery.id, results, cachedTime, isPersonal, nextOffset, switchPmText, switchPmParameter)
suspend fun TelegramBot.answer( suspend fun TelegramBot.answer(
@@ -34,6 +64,6 @@ suspend fun TelegramBot.answer(
cachedTime: Int? = null, cachedTime: Int? = null,
isPersonal: Boolean? = null, isPersonal: Boolean? = null,
nextOffset: String? = null, nextOffset: String? = null,
switchPmText: String? = null, switchPmText: String?,
switchPmParameter: String? = null switchPmParameter: String?
) = answerInlineQuery(inlineQuery.id, results, cachedTime, isPersonal, nextOffset, switchPmText, switchPmParameter) ) = answerInlineQuery(inlineQuery.id, results, cachedTime, isPersonal, nextOffset, switchPmText, switchPmParameter)

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.GetMyName
import dev.inmo.tgbotapi.types.commands.BotCommandScope
import dev.inmo.tgbotapi.types.commands.BotCommandScopeDefault
suspend fun TelegramBot.getMyName(
languageCode: IetfLanguageCode? = null
) = execute(GetMyName(languageCode))
suspend fun TelegramBot.getMyName(
languageCode: String?
) = getMyName(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,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.GetMyName
import dev.inmo.tgbotapi.requests.bot.SetMyName
import dev.inmo.tgbotapi.types.commands.BotCommandScope
import dev.inmo.tgbotapi.types.commands.BotCommandScopeDefault
suspend fun TelegramBot.setMyName(
name: String? = null,
languageCode: IetfLanguageCode? = null
) = execute(SetMyName(name, languageCode))
suspend fun TelegramBot.setMyName(
name: String?,
languageCode: String?
) = setMyName(name, 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

@@ -0,0 +1,114 @@
package dev.inmo.tgbotapi.extensions.api.edit
import dev.inmo.tgbotapi.abstracts.TextedWithTextSources
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.api.edit.caption.editMessageCaption
import dev.inmo.tgbotapi.extensions.api.edit.location.live.editLiveLocation
import dev.inmo.tgbotapi.extensions.api.edit.media.editMessageMedia
import dev.inmo.tgbotapi.extensions.api.edit.reply_markup.editMessageReplyMarkup
import dev.inmo.tgbotapi.extensions.api.edit.text.editMessageText
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
import dev.inmo.tgbotapi.types.chat.Chat
import dev.inmo.tgbotapi.types.location.LiveLocation
import dev.inmo.tgbotapi.types.media.TelegramMedia
import dev.inmo.tgbotapi.types.message.ParseMode
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.Message
import dev.inmo.tgbotapi.types.message.content.*
import dev.inmo.tgbotapi.types.message.textsources.TextSource
import dev.inmo.tgbotapi.types.message.textsources.TextSourcesList
import dev.inmo.tgbotapi.utils.EntitiesBuilderBody
import dev.inmo.tgbotapi.utils.buildEntities
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun TelegramBot.edit(
messageId: InlineMessageIdentifier,
latitude: Double,
longitude: Double,
horizontalAccuracy: Meters? = null,
heading: Degrees? = null,
proximityAlertRadius: Meters? = null,
replyMarkup: InlineKeyboardMarkup? = null
) = editLiveLocation(messageId, latitude, longitude, horizontalAccuracy, heading, proximityAlertRadius, replyMarkup)
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun TelegramBot.edit(
messageId: InlineMessageIdentifier,
location: LiveLocation,
replyMarkup: InlineKeyboardMarkup? = null
) = editLiveLocation(
messageId, location, replyMarkup
)
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun TelegramBot.edit(
messageId: InlineMessageIdentifier,
media: TelegramMedia,
replyMarkup: InlineKeyboardMarkup? = null
) = editMessageMedia(messageId, media, replyMarkup)
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun TelegramBot.edit(
messageId: InlineMessageIdentifier,
replyMarkup: InlineKeyboardMarkup? = null
) = editMessageReplyMarkup(messageId, replyMarkup)
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun TelegramBot.edit(
messageId: InlineMessageIdentifier,
text: String,
parseMode: ParseMode? = null,
disableWebPagePreview: Boolean? = null,
replyMarkup: InlineKeyboardMarkup? = null
) = editMessageText(messageId, text, parseMode, disableWebPagePreview, replyMarkup)
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun TelegramBot.edit(
messageId: InlineMessageIdentifier,
entities: TextSourcesList,
disableWebPagePreview: Boolean? = null,
replyMarkup: InlineKeyboardMarkup? = null
) = editMessageText(messageId, entities, disableWebPagePreview, replyMarkup)
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun TelegramBot.edit(
messageId: InlineMessageIdentifier,
separator: TextSource? = null,
disableWebPagePreview: Boolean? = null,
replyMarkup: InlineKeyboardMarkup? = null,
builderBody: EntitiesBuilderBody
) = edit(messageId, buildEntities(separator, builderBody), disableWebPagePreview, replyMarkup)
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
suspend fun TelegramBot.edit(
messageId: InlineMessageIdentifier,
separator: String,
disableWebPagePreview: Boolean? = null,
replyMarkup: InlineKeyboardMarkup? = null,
builderBody: EntitiesBuilderBody
) = edit(messageId, buildEntities(separator, builderBody), disableWebPagePreview, replyMarkup)

View File

@@ -10,6 +10,17 @@ import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard] * @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that * as a builder for that
*/ */
suspend fun TelegramBot.editMessageMedia(
inlineMessageId: InlineMessageIdentifier,
media: TelegramMedia,
replyMarkup: InlineKeyboardMarkup? = null
) = execute(EditInlineMessageMedia(inlineMessageId, media, replyMarkup))
/**
* @param replyMarkup Some [InlineKeyboardMarkup]. See [dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard]
* as a builder for that
*/
@Deprecated("Renamed", ReplaceWith("this.editMessageMedia(inlineMessageId, media, replyMarkup)", "dev.inmo.tgbotapi.extensions.api.edit.media.editMessageMedia"))
suspend fun TelegramBot.editMessageCaption( suspend fun TelegramBot.editMessageCaption(
inlineMessageId: InlineMessageIdentifier, inlineMessageId: InlineMessageIdentifier,
media: TelegramMedia, media: TelegramMedia,

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

@@ -93,8 +93,9 @@ interface BehaviourContextWithFSM<T : State> : BehaviourContext, StatesMachine<T
behaviourContext: BehaviourContext, behaviourContext: BehaviourContext,
handlers: List<BehaviourWithFSMStateHandlerHolder<*, T>>, handlers: List<BehaviourWithFSMStateHandlerHolder<*, T>>,
statesManager: StatesManager<T>, statesManager: StatesManager<T>,
fallbackHandler: BehaviourWithFSMStateHandlerHolder<T, T>? = null,
onStateHandlingErrorHandler: StateHandlingErrorHandler<T> = defaultStateHandlingErrorHandler() onStateHandlingErrorHandler: StateHandlingErrorHandler<T> = defaultStateHandlingErrorHandler()
) = DefaultBehaviourContextWithFSM<T>(behaviourContext, statesManager, handlers, onStateHandlingErrorHandler) ) = DefaultBehaviourContextWithFSM<T>(behaviourContext, statesManager, handlers, fallbackHandler, onStateHandlingErrorHandler)
} }
} }
@@ -129,11 +130,12 @@ class DefaultBehaviourContextWithFSM<T : State>(
private val behaviourContext: BehaviourContext, private val behaviourContext: BehaviourContext,
private val statesManager: StatesManager<T>, private val statesManager: StatesManager<T>,
private val handlers: List<BehaviourWithFSMStateHandlerHolder<*, T>>, private val handlers: List<BehaviourWithFSMStateHandlerHolder<*, T>>,
private val fallbackHandler: BehaviourWithFSMStateHandlerHolder<T, T>? = null,
private val onStateHandlingErrorHandler: StateHandlingErrorHandler<T> = defaultStateHandlingErrorHandler() private val onStateHandlingErrorHandler: StateHandlingErrorHandler<T> = defaultStateHandlingErrorHandler()
) : BehaviourContext by behaviourContext, BehaviourContextWithFSM<T> { ) : BehaviourContext by behaviourContext, BehaviourContextWithFSM<T> {
private val updatesFlows = mutableMapOf<Any, DefaultBehaviourContextWithFSM<T>>() private val updatesFlows = mutableMapOf<Any, DefaultBehaviourContextWithFSM<T>>()
private val additionalHandlers = mutableListOf<BehaviourWithFSMStateHandlerHolder<*, T>>() private val additionalHandlers = mutableListOf<BehaviourWithFSMStateHandlerHolder<*, T>>()
private var actualHandlersList = additionalHandlers + handlers private var actualHandlersList = additionalHandlers + handlers + listOfNotNull(fallbackHandler)
protected val statesJobs = mutableMapOf<T, Job>() protected val statesJobs = mutableMapOf<T, Job>()
protected val statesJobsMutex = Mutex() protected val statesJobsMutex = Mutex()
@@ -250,6 +252,7 @@ class DefaultBehaviourContextWithFSM<T : State>(
behaviourContext.copy(bot, scope, broadcastChannelsSize, onBufferOverflow, upstreamUpdatesFlow, triggersHolder), behaviourContext.copy(bot, scope, broadcastChannelsSize, onBufferOverflow, upstreamUpdatesFlow, triggersHolder),
handlers, handlers,
statesManager, statesManager,
fallbackHandler,
onStateHandlingErrorHandler onStateHandlingErrorHandler
) )
@@ -265,6 +268,7 @@ class DefaultBehaviourContextWithFSM<T : State>(
behaviourContext.copy(bot, scope, broadcastChannelsSize, onBufferOverflow, upstreamUpdatesFlow, triggersHolder), behaviourContext.copy(bot, scope, broadcastChannelsSize, onBufferOverflow, upstreamUpdatesFlow, triggersHolder),
handlers, handlers,
statesManager, statesManager,
fallbackHandler,
onStateHandlingErrorHandler onStateHandlingErrorHandler
) )
} }

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.*
@@ -29,6 +31,7 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSM(
defaultExceptionsHandler: ExceptionHandler<Unit>? = null, defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()), statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(), presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(),
fallbackHandler: BehaviourWithFSMStateHandlerHolder<T, T>? = null,
onStateHandlingErrorHandler: StateHandlingErrorHandler<T> = defaultStateHandlingErrorHandler(), onStateHandlingErrorHandler: StateHandlingErrorHandler<T> = defaultStateHandlingErrorHandler(),
block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit> block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit>
): DefaultBehaviourContextWithFSM<T> = BehaviourContextWithFSM( ): DefaultBehaviourContextWithFSM<T> = BehaviourContextWithFSM(
@@ -39,6 +42,7 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSM(
), ),
presetHandlers, presetHandlers,
statesManager, statesManager,
fallbackHandler,
onStateHandlingErrorHandler onStateHandlingErrorHandler
).apply { block() } ).apply { block() }
@@ -46,6 +50,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,
@@ -53,7 +61,12 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
defaultExceptionsHandler: ExceptionHandler<Unit>? = null, defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()), statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(), presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(),
fallbackHandler: BehaviourWithFSMStateHandlerHolder<T, T>? = null,
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,
@@ -61,12 +74,13 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
defaultExceptionsHandler, defaultExceptionsHandler,
statesManager, statesManager,
presetHandlers, presetHandlers,
fallbackHandler,
onStateHandlingErrorHandler, onStateHandlingErrorHandler,
block block
).run { ).run {
this to scope.launch { this to scope.launch {
start() start()
longPolling(flowsUpdatesFilter, scope = scope) longPolling(flowsUpdatesFilter, timeoutSeconds, scope, autoDisableWebhooks, autoSkipTimeoutExceptions, mediaGroupsDebounceTimeMillis, defaultExceptionsHandler)
} }
} }
@@ -94,6 +108,7 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSM(
defaultExceptionsHandler: ExceptionHandler<Unit>? = null, defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()), statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(), presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(),
fallbackHandler: BehaviourWithFSMStateHandlerHolder<T, T>? = null,
onStateHandlingErrorHandler: StateHandlingErrorHandler<T> = defaultStateHandlingErrorHandler(), onStateHandlingErrorHandler: StateHandlingErrorHandler<T> = defaultStateHandlingErrorHandler(),
block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit> block: CustomBehaviourContextReceiver<DefaultBehaviourContextWithFSM<T>, Unit>
): DefaultBehaviourContextWithFSM<T> = BehaviourContextWithFSM( ): DefaultBehaviourContextWithFSM<T> = BehaviourContextWithFSM(
@@ -104,6 +119,7 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSM(
), ),
presetHandlers, presetHandlers,
statesManager, statesManager,
fallbackHandler,
onStateHandlingErrorHandler onStateHandlingErrorHandler
).apply { block() } ).apply { block() }
@@ -112,6 +128,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
@@ -123,7 +143,12 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
defaultExceptionsHandler: ExceptionHandler<Unit>? = null, defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()), statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(), presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(),
fallbackHandler: BehaviourWithFSMStateHandlerHolder<T, T>? = null,
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(
@@ -132,13 +157,19 @@ suspend fun <T : State> TelegramBot.buildBehaviourWithFSMAndStartLongPolling(
defaultExceptionsHandler, defaultExceptionsHandler,
statesManager, statesManager,
presetHandlers, presetHandlers,
fallbackHandler,
onStateHandlingErrorHandler, onStateHandlingErrorHandler,
block block
).run { ).run {
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]
@@ -40,8 +46,13 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSM(
defaultExceptionsHandler: ExceptionHandler<Unit>? = null, defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()), statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(), presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(),
fallbackHandler: BehaviourWithFSMStateHandlerHolder<T, T>? = null,
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,
@@ -55,7 +66,12 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSM(
defaultExceptionsHandler, defaultExceptionsHandler,
statesManager, statesManager,
presetHandlers, presetHandlers,
fallbackHandler,
onStateHandlingErrorHandler, onStateHandlingErrorHandler,
timeoutSeconds,
autoDisableWebhooks,
autoSkipTimeoutExceptions,
mediaGroupsDebounceTimeMillis,
block block
) )
} }
@@ -64,6 +80,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
* *
@@ -79,8 +99,13 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSMAndStartLongPolling(
defaultExceptionsHandler: ExceptionHandler<Unit>? = null, defaultExceptionsHandler: ExceptionHandler<Unit>? = null,
statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()), statesManager: StatesManager<T> = DefaultStatesManager(InMemoryDefaultStatesManagerRepo()),
presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(), presetHandlers: List<BehaviourWithFSMStateHandlerHolder<*, T>> = listOf(),
fallbackHandler: BehaviourWithFSMStateHandlerHolder<T, T>? = null,
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(
@@ -94,7 +119,12 @@ suspend fun <T : State> telegramBotWithBehaviourAndFSMAndStartLongPolling(
defaultExceptionsHandler, defaultExceptionsHandler,
statesManager, statesManager,
presetHandlers, presetHandlers,
fallbackHandler,
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,7 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder
import dev.inmo.micro_utils.coroutines.* import dev.inmo.micro_utils.coroutines.*
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers_registrar.TriggersHolder import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers_registrar.TriggersHolder
import dev.inmo.tgbotapi.types.UpdateIdentifier
import dev.inmo.tgbotapi.types.update.abstracts.Update import dev.inmo.tgbotapi.types.update.abstracts.Update
import dev.inmo.tgbotapi.updateshandlers.* import dev.inmo.tgbotapi.updateshandlers.*
import kotlinx.coroutines.* import kotlinx.coroutines.*
@@ -71,9 +72,17 @@ class DefaultBehaviourContext(
private val additionalUpdatesSharedFlow = MutableSharedFlow<Update>(0, broadcastChannelsSize, onBufferOverflow) private val additionalUpdatesSharedFlow = MutableSharedFlow<Update>(0, broadcastChannelsSize, onBufferOverflow)
override val allUpdatesFlow: Flow<Update> = (additionalUpdatesSharedFlow.asSharedFlow()).let { override val allUpdatesFlow: Flow<Update> = (additionalUpdatesSharedFlow.asSharedFlow()).let {
if (upstreamUpdatesFlow != null) { if (upstreamUpdatesFlow != null) {
var lastHandledUpdate = -1L val handledUpdates = mutableSetOf<UpdateIdentifier>()
(it + upstreamUpdatesFlow).filter { (it + upstreamUpdatesFlow).filter {
(it.updateId > lastHandledUpdate).also { passed -> if (passed) { lastHandledUpdate = it.updateId } } val passed = handledUpdates.add(it.updateId)
(passed).also { passed ->
val needToDropCount = handledUpdates.size - broadcastChannelsSize
if (needToDropCount > 0) {
handledUpdates.removeAll(
handledUpdates.take(needToDropCount).ifEmpty { return@also }
)
}
}
} }
} else { } else {
it it

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

@@ -21,3 +21,17 @@ suspend fun BehaviourContext.waitDeepLinks(
.flattenCommandsWithParams().mapNotNull { .flattenCommandsWithParams().mapNotNull {
it.first to (it.second.second.singleOrNull() ?.regularTextSourceOrNull() ?.source ?.removePrefix(" ") ?: return@mapNotNull null) it.first to (it.second.second.singleOrNull() ?.regularTextSourceOrNull() ?.source ?.removePrefix(" ") ?: return@mapNotNull null)
} }
suspend fun BehaviourContext.waitDeepLinks(
regex: Regex,
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null },
): Flow<Pair<CommonMessage<TextContent>, String>> = waitDeepLinks(initRequest, errorFactory).filter {
regex.matches(it.second)
}
suspend fun BehaviourContext.waitDeepLinks(
deepLink: String,
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null },
): Flow<Pair<CommonMessage<TextContent>, String>> = waitDeepLinks(Regex("^$deepLink$"), 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)
@@ -46,3 +46,24 @@ suspend fun <BC : BehaviourContext> BC.onDeepLink(
this@onDeepLink.launchSafelyWithoutExceptions { triggersHolder.handleableCommandsHolder.unregisterHandleable(startRegex) } this@onDeepLink.launchSafelyWithoutExceptions { triggersHolder.handleableCommandsHolder.unregisterHandleable(startRegex) }
} }
} }
suspend fun <BC : BehaviourContext> BC.onDeepLink(
regex: Regex,
initialFilter: SimpleFilter<Pair<TextMessage, String>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, Pair<TextMessage, String>, Update> = { (message, _), update -> MessageFilterByChat(this, message, update) },
markerFactory: MarkerFactory<Pair<TextMessage, String>, Any> = MarkerFactory { (message, _) -> ByChatMessageMarkerFactory(message) },
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, Pair<TextMessage, String>>
): Job {
val internalFilter = SimpleFilter<Pair<TextMessage, String>> {
regex.matches(it.second)
}
return onDeepLink(initialFilter ?.let { internalFilter * it } ?: internalFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
}
suspend fun <BC : BehaviourContext> BC.onDeepLink(
deepLink: String,
initialFilter: SimpleFilter<Pair<TextMessage, String>>? = null,
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, Pair<TextMessage, String>, Update> = { (message, _), update -> MessageFilterByChat(this, message, update) },
markerFactory: MarkerFactory<Pair<TextMessage, String>, Any> = MarkerFactory { (message, _) -> ByChatMessageMarkerFactory(message) },
scenarioReceiver: CustomBehaviourContextAndTypeReceiver<BC, Unit, Pair<TextMessage, String>>
): Job = onDeepLink(Regex("^$deepLink$"), initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)

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

@@ -0,0 +1,6 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
actual var defaultCoroutineScopeProvider: () -> CoroutineScope = { CoroutineScope(Dispatchers.Default) }

View File

@@ -0,0 +1,6 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
actual var defaultCoroutineScopeProvider: () -> CoroutineScope = { CoroutineScope(Dispatchers.Default) }

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
@@ -46,11 +48,23 @@ kotlin {
api libs.javax.activation api libs.javax.activation
} }
} }
linuxX64Main {
dependencies {
api libs.ktor.client.curl
}
}
mingwX64Main {
dependencies {
api libs.ktor.client.winhttp
}
}
} }
} }
dependencies { dependencies {
add("kspJvm", project(":tgbotapi.ksp")) add("kspCommonMainMetadata", project(":tgbotapi.ksp"))
} }
ksp { ksp {

View File

@@ -0,0 +1,10 @@
package dev.inmo.tgbotapi.abstracts
import dev.inmo.tgbotapi.types.chat.Chat
/**
* All inheritors of this interface have [chat] field and related to this [chat]
*/
interface WithChat {
val chat: Chat
}

View File

@@ -1,134 +1,25 @@
package dev.inmo.tgbotapi.bot.ktor package dev.inmo.tgbotapi.bot.ktor
import dev.inmo.micro_utils.coroutines.runCatchingSafely
import dev.inmo.micro_utils.coroutines.safely
import dev.inmo.tgbotapi.bot.BaseRequestsExecutor import dev.inmo.tgbotapi.bot.BaseRequestsExecutor
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.bot.exceptions.*
import dev.inmo.tgbotapi.bot.ktor.base.*
import dev.inmo.tgbotapi.bot.settings.limiters.ExceptionsOnlyLimiter import dev.inmo.tgbotapi.bot.settings.limiters.ExceptionsOnlyLimiter
import dev.inmo.tgbotapi.bot.settings.limiters.RequestLimiter import dev.inmo.tgbotapi.bot.settings.limiters.RequestLimiter
import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import dev.inmo.tgbotapi.types.Response import dev.inmo.tgbotapi.utils.nonstrictJsonFormat
import dev.inmo.tgbotapi.utils.* import io.ktor.client.*
import io.ktor.client.HttpClient
import io.ktor.client.plugins.*
import io.ktor.client.statement.bodyAsText
import io.ktor.client.statement.readText
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
@RiskFeature /**
fun createTelegramBotDefaultKtorCallRequestsFactories() = listOf( * Represents default [BaseRequestsExecutor] working on [Ktor](https://ktor.io) [HttpClient]
SimpleRequestCallFactory(), *
MultipartRequestCallFactory(), * * On JS, JVM and MingwX64 platforms it is [dev.inmo.tgbotapi.bot.ktor.base.DefaultKtorRequestsExecutor]
DownloadFileRequestCallFactory, * * On LinuxX64 it is [dev.inmo.tgbotapi.bot.ktor.base.MultipleClientKtorRequestsExecutor]
DownloadFileChannelRequestCallFactory */
) expect class KtorRequestsExecutor (
class KtorRequestsExecutor(
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper, telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper,
client: HttpClient = HttpClient(), client: HttpClient = HttpClient(),
callsFactories: List<KtorCallFactory> = emptyList(), callsFactories: List<KtorCallFactory> = emptyList(),
excludeDefaultFactories: Boolean = false, excludeDefaultFactories: Boolean = false,
private val requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter, requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter,
private val jsonFormatter: Json = nonstrictJsonFormat, jsonFormatter: Json = nonstrictJsonFormat,
private val pipelineStepsHolder: KtorPipelineStepsHolder = KtorPipelineStepsHolder pipelineStepsHolder: KtorPipelineStepsHolder = KtorPipelineStepsHolder
) : BaseRequestsExecutor(telegramAPIUrlsKeeper) { ) : BaseRequestsExecutor
private val callsFactories: List<KtorCallFactory> = callsFactories.run {
if (!excludeDefaultFactories) {
this + createTelegramBotDefaultKtorCallRequestsFactories()
} else {
this
}
}
private val client = client.config {
if (client.pluginOrNull(HttpTimeout) == null) {
install(HttpTimeout)
}
}
override suspend fun <T : Any> execute(request: Request<T>): T {
return runCatchingSafely {
pipelineStepsHolder.onBeforeSearchCallFactory(request, callsFactories)
requestsLimiter.limit(request) {
var result: T? = null
lateinit var factoryHandledRequest: KtorCallFactory
for (potentialFactory in callsFactories) {
pipelineStepsHolder.onBeforeCallFactoryMakeCall(request, potentialFactory)
result = potentialFactory.makeCall(
client,
telegramAPIUrlsKeeper,
request,
jsonFormatter
)
result = pipelineStepsHolder.onAfterCallFactoryMakeCall(result, request, potentialFactory)
if (result != null) {
factoryHandledRequest = potentialFactory
break
}
}
result ?.let {
pipelineStepsHolder.onRequestResultPresented(it, request, factoryHandledRequest, callsFactories)
} ?: pipelineStepsHolder.onRequestResultAbsent(request, callsFactories) ?: error("Can't execute request: $request")
}
}.let {
val result = it.exceptionOrNull() ?.let { e ->
pipelineStepsHolder.onRequestException(request, e) ?.let { return@let it }
when (e) {
is ClientRequestException -> {
val exceptionResult = runCatchingSafely {
val content = e.response.bodyAsText()
val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content)
newRequestException(
responseObject,
content,
"Can't get result object from $content"
)
}
exceptionResult.exceptionOrNull() ?.let {
CommonBotException(cause = e)
} ?: exceptionResult.getOrThrow()
}
is BotException -> e
else -> CommonBotException(cause = e)
}
} ?.let { Result.failure(it) } ?: it
pipelineStepsHolder.onRequestReturnResult(result, request, callsFactories)
}
}
override fun close() {
client.close()
}
}
class KtorRequestsExecutorBuilder(
var telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper
) {
var client: HttpClient = HttpClient()
var callsFactories: List<KtorCallFactory> = emptyList()
var excludeDefaultFactories: Boolean = false
var requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter
var jsonFormatter: Json = nonstrictJsonFormat
fun build() = KtorRequestsExecutor(telegramAPIUrlsKeeper, client, callsFactories, excludeDefaultFactories, requestsLimiter, jsonFormatter)
}
inline fun telegramBot(
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper,
builder: KtorRequestsExecutorBuilder.() -> Unit = {}
): TelegramBot = KtorRequestsExecutorBuilder(telegramAPIUrlsKeeper).apply(builder).build()
/**
* Shortcut for [telegramBot]
*/
@Suppress("NOTHING_TO_INLINE")
inline fun telegramBot(
token: String,
apiUrl: String = telegramBotAPIDefaultUrl,
testServer: Boolean = false,
builder: KtorRequestsExecutorBuilder.() -> Unit = {}
): TelegramBot = telegramBot(TelegramAPIUrlsKeeper(token, testServer, apiUrl), builder)

View File

@@ -0,0 +1,54 @@
package dev.inmo.tgbotapi.bot.ktor
import dev.inmo.tgbotapi.bot.BaseRequestsExecutor
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.bot.ktor.base.*
import dev.inmo.tgbotapi.bot.settings.limiters.ExceptionsOnlyLimiter
import dev.inmo.tgbotapi.bot.settings.limiters.RequestLimiter
import dev.inmo.tgbotapi.utils.*
import io.ktor.client.HttpClient
import kotlinx.serialization.json.Json
@RiskFeature
fun createTelegramBotDefaultKtorCallRequestsFactories() = listOf(
SimpleRequestCallFactory(),
MultipartRequestCallFactory(),
DownloadFileRequestCallFactory,
DownloadFileChannelRequestCallFactory
)
class KtorRequestsExecutorBuilder(
var telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper
) {
var client: HttpClient = HttpClient()
var callsFactories: List<KtorCallFactory> = emptyList()
var excludeDefaultFactories: Boolean = false
var requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter
var jsonFormatter: Json = nonstrictJsonFormat
fun build() = KtorRequestsExecutor(
telegramAPIUrlsKeeper,
client,
callsFactories,
excludeDefaultFactories,
requestsLimiter,
jsonFormatter
)
}
inline fun telegramBot(
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper,
builder: KtorRequestsExecutorBuilder.() -> Unit = {}
): TelegramBot = KtorRequestsExecutorBuilder(telegramAPIUrlsKeeper).apply(builder).build()
/**
* Shortcut for [telegramBot]
*/
@Suppress("NOTHING_TO_INLINE")
inline fun telegramBot(
token: String,
apiUrl: String = telegramBotAPIDefaultUrl,
testServer: Boolean = false,
builder: KtorRequestsExecutorBuilder.() -> Unit = {}
): TelegramBot = telegramBot(TelegramAPIUrlsKeeper(token, testServer, apiUrl), builder)

View File

@@ -1,6 +1,6 @@
package dev.inmo.tgbotapi.bot.ktor.base package dev.inmo.tgbotapi.bot.ktor.base
import dev.inmo.micro_utils.coroutines.safelyWithResult import dev.inmo.micro_utils.coroutines.runCatchingSafely
import dev.inmo.tgbotapi.bot.ktor.KtorCallFactory import dev.inmo.tgbotapi.bot.ktor.KtorCallFactory
import dev.inmo.tgbotapi.bot.exceptions.newRequestException import dev.inmo.tgbotapi.bot.exceptions.newRequestException
import dev.inmo.tgbotapi.requests.GetUpdates import dev.inmo.tgbotapi.requests.GetUpdates
@@ -56,7 +56,7 @@ abstract class AbstractRequestCallFactory : KtorCallFactory {
val content = response.bodyAsText() val content = response.bodyAsText()
val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content) val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content)
return safelyWithResult { return runCatchingSafely {
(responseObject.result?.let { (responseObject.result?.let {
jsonFormatter.decodeFromJsonElement(request.resultDeserializer, it) jsonFormatter.decodeFromJsonElement(request.resultDeserializer, it)
} ?: response.let { } ?: response.let {

View File

@@ -0,0 +1,100 @@
package dev.inmo.tgbotapi.bot.ktor.base
import dev.inmo.micro_utils.coroutines.runCatchingSafely
import dev.inmo.tgbotapi.bot.BaseRequestsExecutor
import dev.inmo.tgbotapi.bot.exceptions.BotException
import dev.inmo.tgbotapi.bot.exceptions.CommonBotException
import dev.inmo.tgbotapi.bot.exceptions.newRequestException
import dev.inmo.tgbotapi.bot.ktor.KtorCallFactory
import dev.inmo.tgbotapi.bot.ktor.KtorPipelineStepsHolder
import dev.inmo.tgbotapi.bot.ktor.createTelegramBotDefaultKtorCallRequestsFactories
import dev.inmo.tgbotapi.bot.settings.limiters.ExceptionsOnlyLimiter
import dev.inmo.tgbotapi.bot.settings.limiters.RequestLimiter
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.types.Response
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import dev.inmo.tgbotapi.utils.nonstrictJsonFormat
import io.ktor.client.*
import io.ktor.client.plugins.*
import io.ktor.client.statement.*
import kotlinx.serialization.json.Json
class DefaultKtorRequestsExecutor(
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper,
client: HttpClient = HttpClient(),
callsFactories: List<KtorCallFactory> = emptyList(),
excludeDefaultFactories: Boolean = false,
private val requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter,
private val jsonFormatter: Json = nonstrictJsonFormat,
private val pipelineStepsHolder: KtorPipelineStepsHolder = KtorPipelineStepsHolder
) : BaseRequestsExecutor(telegramAPIUrlsKeeper) {
private val callsFactories: List<KtorCallFactory> = callsFactories.run {
if (!excludeDefaultFactories) {
this + createTelegramBotDefaultKtorCallRequestsFactories()
} else {
this
}
}
private val client = client.config {
if (client.pluginOrNull(HttpTimeout) == null) {
install(HttpTimeout)
}
}
override suspend fun <T : Any> execute(request: Request<T>): T {
return runCatchingSafely {
pipelineStepsHolder.onBeforeSearchCallFactory(request, callsFactories)
requestsLimiter.limit(request) {
var result: T? = null
lateinit var factoryHandledRequest: KtorCallFactory
for (potentialFactory in callsFactories) {
pipelineStepsHolder.onBeforeCallFactoryMakeCall(request, potentialFactory)
result = potentialFactory.makeCall(
client,
telegramAPIUrlsKeeper,
request,
jsonFormatter
)
result = pipelineStepsHolder.onAfterCallFactoryMakeCall(result, request, potentialFactory)
if (result != null) {
factoryHandledRequest = potentialFactory
break
}
}
result ?.let {
pipelineStepsHolder.onRequestResultPresented(it, request, factoryHandledRequest, callsFactories)
} ?: pipelineStepsHolder.onRequestResultAbsent(request, callsFactories) ?: error("Can't execute request: $request")
}
}.let {
val result = it.exceptionOrNull() ?.let { e ->
pipelineStepsHolder.onRequestException(request, e) ?.let { return@let it }
when (e) {
is ClientRequestException -> {
val exceptionResult = runCatchingSafely {
val content = e.response.bodyAsText()
val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content)
newRequestException(
responseObject,
content,
"Can't get result object from $content"
)
}
exceptionResult.exceptionOrNull() ?.let {
CommonBotException(cause = e)
} ?: exceptionResult.getOrThrow()
}
is BotException -> e
else -> CommonBotException(cause = e)
}
} ?.let { Result.failure(it) } ?: it
pipelineStepsHolder.onRequestReturnResult(result, request, callsFactories)
}
}
override fun close() {
client.close()
}
}

View File

@@ -4,8 +4,7 @@ import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import dev.inmo.tgbotapi.utils.mapWithCommonValues import dev.inmo.tgbotapi.utils.mapWithCommonValues
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.request.forms.MultiPartFormDataContent import io.ktor.client.request.forms.*
import io.ktor.client.request.forms.formData
import io.ktor.http.Headers import io.ktor.http.Headers
import io.ktor.http.HttpHeaders import io.ktor.http.HttpHeaders

View File

@@ -0,0 +1,118 @@
package dev.inmo.tgbotapi.bot.ktor.base
import dev.inmo.micro_utils.coroutines.runCatchingSafely
import dev.inmo.tgbotapi.bot.BaseRequestsExecutor
import dev.inmo.tgbotapi.bot.ktor.KtorCallFactory
import dev.inmo.tgbotapi.bot.ktor.KtorPipelineStepsHolder
import dev.inmo.tgbotapi.bot.settings.limiters.RequestLimiter
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import io.ktor.client.*
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.serialization.json.Json
/**
* This function is used in default constructor of [MultipleClientKtorRequestsExecutor] and on all non-native
* platforms and MingwX64 should return [client]
*
* On LinuxX64 it will create copy with Curl engine or throw an exception if engine is different with Curl
*
* @throws IllegalArgumentException When pass non Curl-based [HttpClient] on LinuxX64
*/
internal expect inline fun platformClientCopy(client: HttpClient): HttpClient
/**
* Will use its parameters of constructor to create several [DefaultKtorRequestsExecutor] and use them in [execute]
* and [close] operations
*
* This [BaseRequestsExecutor] has been created for LinuxX64 target due to its inability of requests paralleling
*
* Under the hood on each [execute] it will take [DefaultKtorRequestsExecutor] and mark it as busy, execute
* [Request], free up taken [DefaultKtorRequestsExecutor] and return (or throw) the result of execution
*
* @param requestExecutorsCount Amount of [DefaultKtorRequestsExecutor] which will be created and used under the
* hood
*/
class MultipleClientKtorRequestsExecutor (
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper,
callsFactories: List<KtorCallFactory>,
excludeDefaultFactories: Boolean,
requestsLimiter: RequestLimiter,
jsonFormatter: Json,
pipelineStepsHolder: KtorPipelineStepsHolder,
requestExecutorsCount: Int,
clientFactory: () -> HttpClient
) : BaseRequestsExecutor(telegramAPIUrlsKeeper) {
private val requestExecutors = (0 until requestExecutorsCount).map {
DefaultKtorRequestsExecutor(
telegramAPIUrlsKeeper,
clientFactory(),
callsFactories,
excludeDefaultFactories,
requestsLimiter,
jsonFormatter,
pipelineStepsHolder
)
}.toSet()
private val freeClients = MutableStateFlow<Set<DefaultKtorRequestsExecutor>>(requestExecutors)
private val clientAllocationMutex = Mutex()
private val takerFlow = freeClients.mapNotNull {
clientAllocationMutex.withLock {
freeClients.value.firstOrNull() ?.also {
freeClients.value -= it
} ?: return@mapNotNull null
}
}
constructor(
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper,
client: HttpClient,
callsFactories: List<KtorCallFactory>,
excludeDefaultFactories: Boolean,
requestsLimiter: RequestLimiter,
jsonFormatter: Json,
pipelineStepsHolder: KtorPipelineStepsHolder
) : this(
telegramAPIUrlsKeeper,
callsFactories,
excludeDefaultFactories,
requestsLimiter,
jsonFormatter,
pipelineStepsHolder,
client.engineConfig.threadsCount,
{ platformClientCopy(client) }
)
private suspend fun prepareRequestsExecutor(): DefaultKtorRequestsExecutor {
return takerFlow.first()
}
private suspend fun freeRequestsExecutor(client: DefaultKtorRequestsExecutor) {
clientAllocationMutex.withLock {
freeClients.value += client
}
}
private suspend fun <T> withRequestExecutor(block: suspend (DefaultKtorRequestsExecutor) -> T): T {
val requestsExecutor = prepareRequestsExecutor()
val result = runCatchingSafely {
block(requestsExecutor)
}
freeRequestsExecutor(requestsExecutor)
return result.getOrThrow()
}
override suspend fun <T : Any> execute(request: Request<T>): T = withRequestExecutor {
it.execute(request)
}
override fun close() {
requestExecutors.forEach {
it.close()
}
}
}

View File

@@ -1,18 +1,26 @@
package dev.inmo.tgbotapi.bot.settings.limiters package dev.inmo.tgbotapi.bot.settings.limiters
import dev.inmo.micro_utils.coroutines.runCatchingSafely
import dev.inmo.tgbotapi.bot.exceptions.TooMuchRequestsException import dev.inmo.tgbotapi.bot.exceptions.TooMuchRequestsException
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
/** /**
* Simple limiter which will lock any request when [TooMuchRequestsExceptions] is thrown and rerun request after lock time * Simple limiter which will lock any request when [TooMuchRequestsException] is thrown and rerun request after lock time
*/ */
object ExceptionsOnlyLimiter : RequestLimiter { object ExceptionsOnlyLimiter : RequestLimiter {
override suspend fun <T> limit(block: suspend () -> T): T { override suspend fun <T> limit(block: suspend () -> T): T {
return try { var result: Result<T>? = null
block() while (result == null || result.isFailure) {
} catch (e: TooMuchRequestsException) { result = runCatchingSafely {
delay(e.retryAfter.leftToRetry) block()
limit(block) }.onFailure {
if (it is TooMuchRequestsException) {
delay(it.retryAfter.leftToRetry)
} else {
throw it
}
}
} }
return result.getOrThrow()
} }
} }

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

@@ -23,11 +23,30 @@ data class AnswerInlineQuery(
val isPersonal: Boolean? = null, val isPersonal: Boolean? = null,
@SerialName(nextOffsetField) @SerialName(nextOffsetField)
val nextOffset: String? = null, val nextOffset: String? = null,
@SerialName(switchPmTextField) @SerialName(buttonField)
val switchPmText: String? = null, val button: InlineQueryResultsButton? = null,
@SerialName(switchPmParameterField)
val switchPmParameter: String? = null
) : SimpleRequest<Boolean> { ) : SimpleRequest<Boolean> {
constructor(
inlineQueryID: InlineQueryIdentifier,
results: List<InlineQueryResult> = emptyList(),
cachedTime: Int? = null,
isPersonal: Boolean? = null,
nextOffset: String? = null,
switchPmText: String?,
switchPmParameter: String?
) : this(
inlineQueryID,
results,
cachedTime,
isPersonal,
nextOffset,
switchPmText ?.let {
switchPmParameter ?.let {
InlineQueryResultsButton.Start(switchPmText, switchPmParameter)
}
}
)
override fun method(): String = "answerInlineQuery" override fun method(): String = "answerInlineQuery"
override val resultDeserializer: DeserializationStrategy<Boolean> override val resultDeserializer: DeserializationStrategy<Boolean>
get() = Boolean.serializer() get() = Boolean.serializer()
@@ -40,8 +59,23 @@ fun InlineQuery.createAnswer(
cachedTime: Int? = null, cachedTime: Int? = null,
isPersonal: Boolean? = null, isPersonal: Boolean? = null,
nextOffset: String? = null, nextOffset: String? = null,
switchPmText: String? = null, button: InlineQueryResultsButton? = null,
switchPmParameter: String? = null ) = AnswerInlineQuery(
id,
results,
cachedTime,
isPersonal,
nextOffset,
button
)
fun InlineQuery.createAnswer(
results: List<InlineQueryResult> = emptyList(),
cachedTime: Int? = null,
isPersonal: Boolean? = null,
nextOffset: String? = null,
switchPmText: String?,
switchPmParameter: String?
) = AnswerInlineQuery( ) = AnswerInlineQuery(
id, id,
results, results,

View File

@@ -0,0 +1,89 @@
package dev.inmo.tgbotapi.requests.answers
import dev.inmo.micro_utils.common.Warning
import dev.inmo.tgbotapi.types.StartParameter
import dev.inmo.tgbotapi.types.startParameterField
import dev.inmo.tgbotapi.types.textField
import dev.inmo.tgbotapi.types.webAppField
import dev.inmo.tgbotapi.types.webapps.WebAppInfo
import dev.inmo.tgbotapi.utils.internal.ClassCastsIncluded
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
@Serializable(InlineQueryResultsButtonSerializer::class)
@ClassCastsIncluded
sealed interface InlineQueryResultsButton {
val text: String
@Serializable
class Raw internal constructor(
@SerialName(textField)
val text: String,
@SerialName(webAppField)
val webAppInfo: WebAppInfo? = null,
@SerialName(startParameterField)
val deepLinkParameter: String? = null
)
@Serializable(InlineQueryResultsButtonSerializer::class)
data class WebApp(
@SerialName(textField)
override val text: String,
@SerialName(webAppField)
val webAppInfo: WebAppInfo
) : InlineQueryResultsButton
@Serializable(InlineQueryResultsButtonSerializer::class)
data class Start(
@SerialName(textField)
override val text: String,
@SerialName(startParameterField)
val deepLinkParameter: String
) : InlineQueryResultsButton
@Serializable(InlineQueryResultsButtonSerializer::class)
data class Unknown internal constructor (
@SerialName(textField)
override val text: String
) : InlineQueryResultsButton
companion object {
operator fun invoke(
text: String,
deepLinkParameter: String
) = Start(text, deepLinkParameter)
operator fun invoke(
text: String,
webAppInfo: WebAppInfo
) = WebApp(text, webAppInfo)
}
}
object InlineQueryResultsButtonSerializer : KSerializer<InlineQueryResultsButton> {
override val descriptor: SerialDescriptor = InlineQueryResultsButton.Raw.serializer().descriptor
override fun deserialize(decoder: Decoder): InlineQueryResultsButton {
val raw = InlineQueryResultsButton.Raw.serializer().deserialize(decoder)
return when {
raw.webAppInfo != null -> InlineQueryResultsButton.WebApp(raw.text, raw.webAppInfo)
raw.deepLinkParameter != null -> InlineQueryResultsButton.Start(raw.text, raw.deepLinkParameter)
else -> InlineQueryResultsButton.Unknown(raw.text)
}
}
override fun serialize(encoder: Encoder, value: InlineQueryResultsButton) {
InlineQueryResultsButton.Raw.serializer().serialize(
encoder,
InlineQueryResultsButton.Raw(
value.text,
(value as? InlineQueryResultsButton.WebApp)?.webAppInfo,
(value as? InlineQueryResultsButton.Start)?.deepLinkParameter,
)
)
}
}

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 GetMyName(
@SerialName(languageCodeField)
@Serializable(IetfLanguageCodeSerializer::class)
override val ietfLanguageCode: IetfLanguageCode? = null
) : SimpleRequest<BotName>, WithOptionalLanguageCode {
override fun method(): String = "getMyName"
override val resultDeserializer: DeserializationStrategy<BotName>
get() = BotName.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 SetMyName(
@SerialName(nameField)
val name: String? = null,
@SerialName(languageCodeField)
@Serializable(IetfLanguageCodeSerializer::class)
override val ietfLanguageCode: IetfLanguageCode? = null
) : SimpleRequest<Boolean>, WithOptionalLanguageCode {
override fun method(): String = "setMyName"
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

@@ -19,7 +19,7 @@ data class GetChat(
override val resultDeserializer: DeserializationStrategy<ExtendedChat> = if (chatId is ChatIdWithThreadId) { override val resultDeserializer: DeserializationStrategy<ExtendedChat> = if (chatId is ChatIdWithThreadId) {
ExtendedChatSerializer.BasedOnForumThread(chatId.threadId) ExtendedChatSerializer.BasedOnForumThread(chatId.threadId)
} else { } else {
ExtendedChatSerializer ExtendedChatSerializer.Companion
} }
override val requestSerializer: SerializationStrategy<*> override val requestSerializer: SerializationStrategy<*>
get() = serializer() get() = serializer()

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