mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2025-11-17 20:40:20 +00:00
Compare commits
139 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c0a43077ad | |||
| 1811a63a13 | |||
| cba0e30710 | |||
| ff0b7faa48 | |||
| 975898660c | |||
| cfb7f35d20 | |||
| 147889a66a | |||
| ed9ed715a0 | |||
| a9a3f55c8d | |||
| 58943f2504 | |||
| 5f7633a57e | |||
| 65cfc3220d | |||
| 36d30ef91b | |||
| 41e5c579a2 | |||
| bbf63c51ec | |||
| fb91199f83 | |||
| d76c09ffb2 | |||
| acfb7066d2 | |||
| 7507c107b4 | |||
| 2acb177ad6 | |||
| b5a14077fd | |||
| 5f60bf003f | |||
| f9b2c4c403 | |||
| c909774403 | |||
| 670cfcca13 | |||
| 130e00b62b | |||
| ca4beee95f | |||
| ca784e67df | |||
| 835b8b34f9 | |||
| e6430a729c | |||
| 6c4c9f2fc6 | |||
| 310a7e6e82 | |||
| 7375894645 | |||
| 69973c597b | |||
| 22e8b06fda | |||
| 7ede53fdbb | |||
| ca9051920d | |||
| b477e8d585 | |||
| 8ae2f57d55 | |||
| 1fb2ecf15f | |||
| 6073d914d5 | |||
| 16f55d70af | |||
| b484a31a4a | |||
| 0a162c4129 | |||
| 648f1b488b | |||
| 5fbde4bc06 | |||
| 2a276d9272 | |||
| 9ae252717d | |||
| 456143a266 | |||
| 0bcc98e126 | |||
| ab9ceba41c | |||
| 7cd5666e88 | |||
| 35dcd6ada7 | |||
| ec37df82a9 | |||
| 220cb47615 | |||
| d79b8a337a | |||
| cef6a6f741 | |||
| 9471df1f2d | |||
| f121e5f9c3 | |||
| 7f4fe318c5 | |||
| dbf5c2dbb2 | |||
| 105415873d | |||
| ff32fd1dfc | |||
| 006251ed07 | |||
| 9307582654 | |||
| fe11a2119e | |||
| c31403c1a2 | |||
| 0260e7bedc | |||
| fa43a55f26 | |||
| e9e1f4b9cf | |||
| e7b5b9184d | |||
| 81aa3f2307 | |||
| a9fe584504 | |||
| 4c8861ba79 | |||
| 0ec18cbf06 | |||
| 7008f312dc | |||
| 85317a510e | |||
| d629aa206e | |||
| 6394e1a52b | |||
| 23dca3d307 | |||
| 3032aa8474 | |||
| db19b69ca0 | |||
| f3827f81a7 | |||
| 0532dbb1ae | |||
| efc2681da8 | |||
| 735ed9fd86 | |||
| e856dc4754 | |||
| 0706ff1f95 | |||
| 336b830b0b | |||
| 1a638fe0a5 | |||
| 45467e5bd7 | |||
| 8419b0ab6a | |||
| 49573607fb | |||
| 35fe48db35 | |||
| 590db3e672 | |||
| ea40474c47 | |||
| 7354389f2d | |||
| 1f20ae16aa | |||
| 095c91bf39 | |||
| dc173d752c | |||
| a1788e35b2 | |||
| ea224fd765 | |||
| 7f51544bb9 | |||
| dfb22b0e89 | |||
| e675e841da | |||
| dea43aad8e | |||
| 52e25e934d | |||
| acc067585d | |||
| 47aa1a0795 | |||
| b40cc0c1ea | |||
| b5632626ad | |||
| 67fafdac00 | |||
| 738e628a89 | |||
| 420b846466 | |||
| 05e8c9c90d | |||
| e776c5182f | |||
| be5b3745b9 | |||
| 0de1d9cfda | |||
| 01da98d2fe | |||
| e985100c21 | |||
| 671faabef9 | |||
| bb9c9e22a2 | |||
| 42228f0eaa | |||
| dafd0a8ece | |||
| bee9d82372 | |||
| ec6cf0f029 | |||
| 9cee22165d | |||
| a58aad1198 | |||
| aa78d99179 | |||
| 603efe9259 | |||
| 21e3e10222 | |||
| 34eb6eb4bf | |||
| 565a724b9c | |||
| e87c4a0126 | |||
| 9b16d5d82b | |||
| 9747c8bff1 | |||
| 3ee84700f4 | |||
| 04a463f42c | |||
| 668a201789 |
9
.github/labeler.yml
vendored
Normal file
9
.github/labeler.yml
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
api: "TelegramBotAPI-extensions-api/**"
|
||||||
|
utils: "TelegramBotAPI-extensions-utils/**"
|
||||||
|
core: "TelegramBotAPI/**" # currently not work
|
||||||
|
|
||||||
|
code: "**/*.kt"
|
||||||
|
gradle: "**/*.gradle"
|
||||||
|
markdown:
|
||||||
|
- "**/*.md"
|
||||||
|
- "!CHANGELOG.md"
|
||||||
13
.github/workflows/greetings.yml
vendored
Normal file
13
.github/workflows/greetings.yml
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
name: Greetings
|
||||||
|
|
||||||
|
on: [pull_request, issues]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
greeting:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/first-interaction@v1
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
issue-message: 'Welcome with your first issue'
|
||||||
|
pr-message: 'Welcome with your first PullRequest'
|
||||||
18
.github/workflows/label.yml
vendored
Normal file
18
.github/workflows/label.yml
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# This workflow will triage pull requests and apply a label based on the
|
||||||
|
# paths that are modified in the pull request.
|
||||||
|
#
|
||||||
|
# To use this workflow, you will need to set up a .github/labeler.yml
|
||||||
|
# file with configuration. For more information, see:
|
||||||
|
# https://github.com/actions/labeler/blob/master/README.md
|
||||||
|
|
||||||
|
name: "Pull Request Labeler"
|
||||||
|
on:
|
||||||
|
- pull_request
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
triage:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/labeler@v2
|
||||||
|
with:
|
||||||
|
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||||
139
CHANGELOG.md
139
CHANGELOG.md
@@ -49,6 +49,145 @@
|
|||||||
* `closePollExactAfter`
|
* `closePollExactAfter`
|
||||||
* `closePollAfter`
|
* `closePollAfter`
|
||||||
|
|
||||||
|
### 0.27.8
|
||||||
|
|
||||||
|
* `TelegramBotAPI`:
|
||||||
|
* `UnknownUpdateType` was renamed to `UnknownUpdate`
|
||||||
|
* Refactoring and optimization of `FlowsUpdatesFilter`
|
||||||
|
* `Venue` type was replaced to a new package: `com.github.insanusmokrassar.TelegramBotAPI.types.venue.Venue`
|
||||||
|
* `Venue` type now implements `Locationed` and delegate realisation to its `location` field
|
||||||
|
* `FoursquareId` and `FoursquareType` typealiases were added
|
||||||
|
* `TelegramBotAPI-extensions-utils`:
|
||||||
|
* Several new functions `makeLinkToMessage` was added
|
||||||
|
* `Foursquare` data class was added
|
||||||
|
* Extension `Venue#foursquare` was added
|
||||||
|
* Factory function `Venue` with `Foursquare` parameter was added
|
||||||
|
|
||||||
|
### 0.27.7
|
||||||
|
|
||||||
|
* `TelegramBotAPI`:
|
||||||
|
* Operator function `unaryPlus` was added to `RowBuilder`. Now it is possible to write `row { +button }`
|
||||||
|
* Function `flatMatrix` was added for single-row columns
|
||||||
|
* Operator extension `RowBuilder#plus` was added to be able to write things like `row { this + button }`
|
||||||
|
* `TelegramBotAPI-extensions-api`:
|
||||||
|
* Extensions `RequestsExecutor#sendVenue` with `Location` args were added
|
||||||
|
* `TelegramBotAPI-extensions-utils`:
|
||||||
|
* Function `InlineKeyboardMarkup` for flat keyboards was added
|
||||||
|
* Function `ReplyKeyboardMarkup` for flat keyboards was added
|
||||||
|
|
||||||
|
### 0.27.6
|
||||||
|
|
||||||
|
* `Common`:
|
||||||
|
* Versions:
|
||||||
|
* `Kotlin Coroutines`: `1.3.6` -> `1.3.7`
|
||||||
|
* `TelegramBotAPI`:
|
||||||
|
* Interface `PossiblySentViaBot` has been added
|
||||||
|
* Additional interface `PossiblySentViaBotCommonMessage` was added for more explicit typing declaration for
|
||||||
|
compiler
|
||||||
|
* Currently, only `ChannelMessage` and `CommonMessageImpl` are implementing the interface
|
||||||
|
`PossiblySentViaBotCommonMessage`. It could be changed in future
|
||||||
|
* Factory `buildMimeType` was added
|
||||||
|
* `BuiltinMimeTypes` was added
|
||||||
|
* Abstraction `ThumbedWithMimeTypeInlineQueryResult` with `thumbMimeType` field was added
|
||||||
|
* `InlineQueryResultGif` and `InlineQueryResultMpeg4Gif` now extend `ThumbedWithMimeTypeInlineQueryResult`
|
||||||
|
instead of `ThumbedInlineQueryResult`
|
||||||
|
* `TelegramBotAPI-extensions-utils`:
|
||||||
|
* New extensions `onlyCommonMessages`, `onlySentViaBot` and `withoutSentViaBot` was added
|
||||||
|
|
||||||
|
### 0.27.5
|
||||||
|
|
||||||
|
* `Common`:
|
||||||
|
* Versions:
|
||||||
|
* `Klock`: `1.11.1` -> `1.11.3`
|
||||||
|
* `TelegramotAPI`:
|
||||||
|
* Fix: for sending requests caption and text lengths limits were updated
|
||||||
|
* New variant of `row` was added
|
||||||
|
* `makeLinkToMessage` extensions has been deprecated (replaced into `TelegramBotAPI-extensions-utils`)
|
||||||
|
* Next things was deprecated and replaced into `TelegramBotAPI-extensions-utils`:
|
||||||
|
* All `String` formatting public extensions and functions
|
||||||
|
* All extensions like `CaptionedInput#toHtmlCaptions`
|
||||||
|
* All helper extensions for `List<BaseMessageUpdate>`
|
||||||
|
* All `RequestsExecutor#executeAsync` and `RequestsExecutor#executeUnsafe`
|
||||||
|
* `BotCommand` now more strictly check commands which passed to it
|
||||||
|
* Regex `BotCommandNameRegex` was added
|
||||||
|
* `TelegramBotAPI-extensions-api`:
|
||||||
|
* A lot of `RequesstExecutor#getChat` extensions was added for more explicit types showing
|
||||||
|
* New `RequesstExecutor#setMyCommands` extension was added
|
||||||
|
* New field `BotBuilder#ktorClientEngineFactory` introduced
|
||||||
|
* Field `BotBuilder#ktorClientEngine` now is deprecated
|
||||||
|
* `TelegramBotAPI-extensions-utils`:
|
||||||
|
* `safely` function was introduced. It is in `PreviewFeature` state currently
|
||||||
|
* `makeLinkToMessage` extensions has been added
|
||||||
|
* `makeLinkToAddStickerSet` function and its variations were added
|
||||||
|
* Next tools was added from `TelegramBotAPI`:
|
||||||
|
* All `String` formatting extensions and functions
|
||||||
|
* All extensions like `CaptionedInput#toHtmlCaptions`
|
||||||
|
* All helper extensions for `List<BaseMessageUpdate>`
|
||||||
|
* Several new extensions for `SentMediaGroupUpdate` were added:
|
||||||
|
* `SentMediaGroupUpdate#forwardInfo`
|
||||||
|
* `SentMediaGroupUpdate#replyTo`
|
||||||
|
* `SentMediaGroupUpdate#chat`
|
||||||
|
* `SentMediaGroupUpdate#mediaGroupId`
|
||||||
|
* Several `List<MediaGroupMessage>.createResend` extensions were added
|
||||||
|
* `RequestsExecutor#executeAsync` and `RequestsExecutor#executeUnsafe`
|
||||||
|
|
||||||
|
### 0.27.4
|
||||||
|
|
||||||
|
* `TelegramBotAPI-extensions-utils`:
|
||||||
|
* Several extensions for updates was added:
|
||||||
|
* `onlyBaseMessageUpdates`
|
||||||
|
* `onlySentMessageUpdates`
|
||||||
|
* `onlyEditMessageUpdates`
|
||||||
|
* `onlyMediaGroupsUpdates`
|
||||||
|
* `onlySentMediaGroupUpdates`
|
||||||
|
* `onlyEditMediaGroupUpdates`
|
||||||
|
* Renames in chat filters extensions:
|
||||||
|
* `filterBaseMessageUpdates` -> `filterBaseMessageUpdatesByChatId` and `filterBaseMessageUpdatesByChat`
|
||||||
|
* `filterSentMediaGroupUpdates` -> `filterSentMediaGroupUpdatesByChatId` and `filterSentMediaGroupUpdatesByChat`
|
||||||
|
|
||||||
|
### 0.27.3
|
||||||
|
|
||||||
|
* `TelegramBotAPI`:
|
||||||
|
* `UpdateDeserializationStrategy` is publicly available now
|
||||||
|
* All `setWebhook` extensions was marked as deprecated, renamed and replaced into `TelegramBotAPI-extensions-utils`
|
||||||
|
* Typealias `ExceptionHandler` was added - it will be used for `handleSafely`
|
||||||
|
* `SetWebhook` factories signatures was changed (backward compatibility was not broken)
|
||||||
|
* `executeUnsafe` now working differently
|
||||||
|
* Now it is possible to pass exceptions handler into `executeUnsafe`
|
||||||
|
* `BasketballDiceAnimationType` was added
|
||||||
|
* `UnknownDiceAnimationType` now is deprecated due to renaming - currently it is typealias for `CustomDiceAnimationType`
|
||||||
|
* `CustomDiceAnimationType` now is `data` class instead of common class
|
||||||
|
* `FlowsUpdatesFilter` will use size 64 by default for internal broadcast channels
|
||||||
|
* `TelegramBotAPI-extensions-api`:
|
||||||
|
* Long Polling extensions now are deprecated in this project. It was replaced into `TelegramBotAPI-extensions-utils`
|
||||||
|
* Several `telegramBot` functions was renamed into `telegramBotWithCustomClientConfig`
|
||||||
|
* Add one more `setWebhookInfo` realisation
|
||||||
|
* `TelegramBotAPI-extensions-utils`:
|
||||||
|
* Extension `toTelegramUpdate` was added
|
||||||
|
* Long Polling extensions were added
|
||||||
|
* Updates utils were added
|
||||||
|
* New extensions `startListenWebhooks`, `setWebhookInfoAndStartListenWebhooks` and `includeWebhookHandlingInRoute` was added
|
||||||
|
* New extension `CoroutineScope#updateHandlerWithMediaGroupsAdaptation` was added
|
||||||
|
* New extension `flowsUpdatesFilter` was added
|
||||||
|
* `TelegramBotAPI-all`:
|
||||||
|
* Project was created
|
||||||
|
|
||||||
|
### 0.27.2
|
||||||
|
|
||||||
|
* `Common`:
|
||||||
|
* Versions:
|
||||||
|
* Coroutines: `1.3.5` -> `1.3.6`
|
||||||
|
* Klock: `1.10.5` -> `1.11.1`
|
||||||
|
* `TelegramBotAPI`:
|
||||||
|
* Expected class `MimeType` was added
|
||||||
|
* Field `MimeTyped#mimeType` now typed by `MimeType` instead of `String`
|
||||||
|
* `MediaGroupMemberInputMedia` children now can be deserialized (but only those ones who are declared inside library)
|
||||||
|
* `TelegramBotAPI-extensions-utils`:
|
||||||
|
* Chat events splitters added:
|
||||||
|
* Extension `Flow<ChatEventMessage>#onlyChannelEvents` was added
|
||||||
|
* Extension `Flow<ChatEventMessage>#onlyGroupEvents` was added
|
||||||
|
* Extension `Flow<ChatEventMessage>#onlySupergroupEvents` was added
|
||||||
|
|
||||||
### 0.27.1
|
### 0.27.1
|
||||||
|
|
||||||
* `TelegramBotAPI`:
|
* `TelegramBotAPI`:
|
||||||
|
|||||||
66
README.md
66
README.md
@@ -1,10 +1,12 @@
|
|||||||
# TelegramBotAPI
|
# TelegramBotAPI
|
||||||
|
|
||||||
| Common info | [](https://github.com/KotlinBy/awesome-kotlin) [](https://t.me/InMoTelegramBotAPI) [](https://travis-ci.com/InsanusMokrassar/TelegramBotAPI) |
|
| Common info | [](https://github.com/KotlinBy/awesome-kotlin) [](https://travis-ci.com/InsanusMokrassar/TelegramBotAPI) |
|
||||||
| -------------------------------------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
| -------------------------------------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| TelegramBotAPI status | [](https://bintray.com/insanusmokrassar/StandardRepository/TelegramBotAPI/_latestVersion) [](https://maven-badges.herokuapp.com/maven-central/com.github.insanusmokrassar/TelegramBotAPI) |
|
| Useful links | [](https://teleg.one/InMoTelegramBotAPI) [](https://tgbotapi.inmo.dev/docs/index.html) [Examples](https://github.com/InsanusMokrassar/TelegramBotAPI-examples/), [Mini tutorial](https://bookstack.inmo.dev/books/telegrambotapi/chapter/introduction-tutorial) |
|
||||||
|
| TelegramBotAPI status | [](https://bintray.com/insanusmokrassar/StandardRepository/TelegramBotAPI/_latestVersion) [](https://maven-badges.herokuapp.com/maven-central/com.github.insanusmokrassar/TelegramBotAPI) |
|
||||||
| TelegramBotAPI Extensions status | [](https://bintray.com/insanusmokrassar/StandardRepository/TelegramBotAPI-extensions-api/_latestVersion) [](https://maven-badges.herokuapp.com/maven-central/com.github.insanusmokrassar/TelegramBotAPI-extensions-api) |
|
| TelegramBotAPI Extensions status | [](https://bintray.com/insanusmokrassar/StandardRepository/TelegramBotAPI-extensions-api/_latestVersion) [](https://maven-badges.herokuapp.com/maven-central/com.github.insanusmokrassar/TelegramBotAPI-extensions-api) |
|
||||||
| TelegramBotAPI Util Extensions status | [](https://bintray.com/insanusmokrassar/StandardRepository/TelegramBotAPI-extensions-utils/_latestVersion) [](https://maven-badges.herokuapp.com/maven-central/com.github.insanusmokrassar/TelegramBotAPI-extensions-utils) |
|
| TelegramBotAPI Util Extensions status | [](https://bintray.com/insanusmokrassar/StandardRepository/TelegramBotAPI-extensions-utils/_latestVersion) [](https://maven-badges.herokuapp.com/maven-central/com.github.insanusmokrassar/TelegramBotAPI-extensions-utils) |
|
||||||
|
| TelegramBotAPI All status | [](https://bintray.com/insanusmokrassar/StandardRepository/TelegramBotAPI-all/_latestVersion) [](https://maven-badges.herokuapp.com/maven-central/com.github.insanusmokrassar/TelegramBotAPI-all) |
|
||||||
|
|
||||||
It is a complex of libraries for working with `TelegramBotAPI` in type-safe and strict way as much as it possible. In
|
It is a complex of libraries for working with `TelegramBotAPI` in type-safe and strict way as much as it possible. In
|
||||||
the list of this complex currently next projects:
|
the list of this complex currently next projects:
|
||||||
@@ -15,6 +17,7 @@ the list of this complex currently next projects:
|
|||||||
`RequestsExecutor`), which allows to use the core library in more pleasant way
|
`RequestsExecutor`), which allows to use the core library in more pleasant way
|
||||||
* [TelegramBotAPI Util Extensions](TelegramBotAPI-extensions-utils/README.md) - contains extensions for more comfortable
|
* [TelegramBotAPI Util Extensions](TelegramBotAPI-extensions-utils/README.md) - contains extensions for more comfortable
|
||||||
work with commands, updates and other different things
|
work with commands, updates and other different things
|
||||||
|
* [TelegramBotAPI All](TelegramBotAPI-all/README.md) - concentration of all previously mentioned libraries
|
||||||
|
|
||||||
Most part of some specific solves or unuseful
|
Most part of some specific solves or unuseful
|
||||||
moments are describing by official [Telegram Bot API](https://core.telegram.org/bots/api).
|
moments are describing by official [Telegram Bot API](https://core.telegram.org/bots/api).
|
||||||
@@ -62,15 +65,66 @@ kotlin {
|
|||||||
|
|
||||||
## Ok, where should I start?
|
## Ok, where should I start?
|
||||||
|
|
||||||
In most cases, the most simple way will be to implement
|

|
||||||
[TelegramBotAPI Extensions](TelegramBotAPI-extensions-api/README.md) and
|
|
||||||
[TelegramBotAPI Util Extensions](TelegramBotAPI-extensions-utils/README.md) for the reason that they contains more
|
In most cases, the most simple way will be to implement [TelegramBotAPI All](TelegramBotAPI-all/README.md) - it contains
|
||||||
simple tools. If you want to dive deeper in the core of library or develop something for it - welcome to
|
all necessary tools for comfort usage of this library. If you want to exclude some libraries, you can implement just
|
||||||
|
[TelegramBotAPI API Extensions](TelegramBotAPI-extensions-api/README.md),
|
||||||
|
[TelegramBotAPI Util Extensions](TelegramBotAPI-extensions-utils/README.md) or even
|
||||||
[TelegramBotAPI](TelegramBotAPI/README.md).
|
[TelegramBotAPI](TelegramBotAPI/README.md).
|
||||||
|
|
||||||
|
If you want to dive deeper in the core of library or develop something for it - welcome to learn more from
|
||||||
|
[TelegramBotAPI](TelegramBotAPI/README.md) and our [Telegram Chat](https://teleg.one/InMoTelegramBotAPIChat).
|
||||||
|
|
||||||
Anyway, all libraries are very typical inside of them. Examples:
|
Anyway, all libraries are very typical inside of them. Examples:
|
||||||
|
|
||||||
* In `TelegramBotAPI` common request look like `requestsExecutor.execute(SomeRequest())`
|
* In `TelegramBotAPI` common request look like `requestsExecutor.execute(SomeRequest())`
|
||||||
* `TelegramBotAPI-extensions-api` typical syntax look like `requestsExecutor.someRequest()` (in most cases it would be
|
* `TelegramBotAPI-extensions-api` typical syntax look like `requestsExecutor.someRequest()` (in most cases it would be
|
||||||
better to use `bot` name instead of `requestsExecutor`)
|
better to use `bot` name instead of `requestsExecutor`)
|
||||||
* `TelegramBotAPI-extensions-utils` will look like `filter.filterBaseMessageUpdates(chatId).filterExactCommands(Regex("^.*$"))...`
|
* `TelegramBotAPI-extensions-utils` will look like `filter.filterBaseMessageUpdates(chatId).filterExactCommands(Regex("^.*$"))...`
|
||||||
|
|
||||||
|
## Build instruction
|
||||||
|
|
||||||
|
If you want to build this project or to contribute, there are several recommendations:
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
In case if you want to just build project, run next command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./gradlew clean build
|
||||||
|
```
|
||||||
|
|
||||||
|
On windows:
|
||||||
|
|
||||||
|
```
|
||||||
|
gradlew.bat clean build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Publishing for work with your version locally
|
||||||
|
|
||||||
|
In case, if you want to work in your other projects using your modification (or some state) of this library,
|
||||||
|
you can use next code:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./gradlew clean build publishToMavenLocal
|
||||||
|
```
|
||||||
|
|
||||||
|
On windows:
|
||||||
|
|
||||||
|
```
|
||||||
|
gradlew.bat clean build publishToMavenLocal
|
||||||
|
```
|
||||||
|
|
||||||
|
But you must remember, that in this case your local maven repo must be the first one from
|
||||||
|
your project retrieving libraries:
|
||||||
|
|
||||||
|
```groovy
|
||||||
|
repositories {
|
||||||
|
mavenLocal() // that must be the first one
|
||||||
|
jcenter()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Besides, for your own version you can change variable `library_version` in the file [gradle.properties](./gradle.properties).
|
||||||
|
|||||||
16
TelegramBotAPI-all/README.md
Normal file
16
TelegramBotAPI-all/README.md
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# TelegramBotAPI-all
|
||||||
|
|
||||||
|
Concentration of all TelegramBotAPI libraries:
|
||||||
|
|
||||||
|
* [TelegramBotAPI](../TelegramBotAPI/README.md)
|
||||||
|
* [TelegramBotAPI Extensions](../TelegramBotAPI-extensions-api/README.md)
|
||||||
|
* [TelegramBotAPI Util Extensions](../TelegramBotAPI-extensions-utils/README.md)
|
||||||
|
|
||||||
|
## Implementation
|
||||||
|
|
||||||
|
```groovy
|
||||||
|
dependencies {
|
||||||
|
// ...
|
||||||
|
implementation "com.github.insanusmokrassar:TelegramBotAPI-all:tgBotAPIVersion"
|
||||||
|
}
|
||||||
|
```
|
||||||
52
TelegramBotAPI-all/build.gradle
Normal file
52
TelegramBotAPI-all/build.gradle
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
jcenter()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
|
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
||||||
|
classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:$gradle_bintray_plugin_version"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id "org.jetbrains.kotlin.multiplatform" version "$kotlin_version"
|
||||||
|
id "org.jetbrains.kotlin.plugin.serialization" version "$kotlin_version"
|
||||||
|
}
|
||||||
|
|
||||||
|
project.version = "$library_version"
|
||||||
|
project.group = "$library_group"
|
||||||
|
|
||||||
|
apply from: "publish.gradle"
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
jcenter()
|
||||||
|
mavenCentral()
|
||||||
|
maven { url "https://kotlin.bintray.com/kotlinx" }
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
jvm()
|
||||||
|
js()
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
commonMain {
|
||||||
|
dependencies {
|
||||||
|
implementation kotlin('stdlib')
|
||||||
|
if ((project.hasProperty('RELEASE_MODE') && project.property('RELEASE_MODE') == "true") || System.getenv('RELEASE_MODE') == "true") {
|
||||||
|
api "${project.group}:TelegramBotAPI:$library_version"
|
||||||
|
api "${project.group}:TelegramBotAPI-extensions-api:$library_version"
|
||||||
|
api "${project.group}:TelegramBotAPI-extensions-utils:$library_version"
|
||||||
|
} else {
|
||||||
|
api project(":TelegramBotAPI")
|
||||||
|
api project(":TelegramBotAPI-extensions-api")
|
||||||
|
api project(":TelegramBotAPI-extensions-utils")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
53
TelegramBotAPI-all/maven.publish.gradle
Normal file
53
TelegramBotAPI-all/maven.publish.gradle
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
apply plugin: 'maven-publish'
|
||||||
|
|
||||||
|
task javadocsJar(type: Jar) {
|
||||||
|
classifier = 'javadoc'
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
project.publishing.publications.all {
|
||||||
|
// rename artifacts
|
||||||
|
groupId "${project.group}"
|
||||||
|
if (it.name.contains('kotlinMultiplatform')) {
|
||||||
|
artifactId = "${project.name}"
|
||||||
|
} else {
|
||||||
|
artifactId = "${project.name}-$name"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications.all {
|
||||||
|
artifact javadocsJar
|
||||||
|
|
||||||
|
pom {
|
||||||
|
description = "This project just include all subproject of TelegramBotAPI"
|
||||||
|
name = "Telegram Bot API All"
|
||||||
|
url = "https://insanusmokrassar.github.io/TelegramBotAPI/TelegramBotAPI-all"
|
||||||
|
|
||||||
|
scm {
|
||||||
|
developerConnection = "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
||||||
|
url = "https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
||||||
|
}
|
||||||
|
|
||||||
|
developers {
|
||||||
|
|
||||||
|
developer {
|
||||||
|
id = "InsanusMokrassar"
|
||||||
|
name = "Ovsiannikov Aleksei"
|
||||||
|
email = "ovsyannikov.alexey95@gmail.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
licenses {
|
||||||
|
|
||||||
|
license {
|
||||||
|
name = "Apache Software License 2.0"
|
||||||
|
url = "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
TelegramBotAPI-all/mpp_publish_template.json
Normal file
1
TelegramBotAPI-all/mpp_publish_template.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"bintrayConfig":{"repo":"StandardRepository","packageName":"${project.name}","packageVcs":"https://github.com/InsanusMokrassar/TelegramBotAPI"},"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"}],"mavenConfig":{"name":"Telegram Bot API All","description":"This project just include all subproject of TelegramBotAPI","url":"https://insanusmokrassar.github.io/TelegramBotAPI/TelegramBotAPI-all","vcsUrl":"https://github.com/insanusmokrassar/TelegramBotAPI.git","developers":[{"id":"InsanusMokrassar","name":"Ovsiannikov Aleksei","eMail":"ovsyannikov.alexey95@gmail.com"}]},"type":"Multiplatform"}
|
||||||
55
TelegramBotAPI-all/publish.gradle
Normal file
55
TelegramBotAPI-all/publish.gradle
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
apply plugin: 'com.jfrog.bintray'
|
||||||
|
|
||||||
|
apply from: "maven.publish.gradle"
|
||||||
|
|
||||||
|
bintray {
|
||||||
|
user = project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER')
|
||||||
|
key = project.hasProperty('BINTRAY_KEY') ? project.property('BINTRAY_KEY') : System.getenv('BINTRAY_KEY')
|
||||||
|
filesSpec {
|
||||||
|
from "${buildDir}/publications/"
|
||||||
|
eachFile {
|
||||||
|
String directorySubname = it.getFile().parentFile.name
|
||||||
|
if (it.getName() == "module.json") {
|
||||||
|
if (directorySubname == "kotlinMultiplatform") {
|
||||||
|
it.setPath("${project.name}/${project.version}/${project.name}-${project.version}.module")
|
||||||
|
} else {
|
||||||
|
it.setPath("${project.name}-${directorySubname}/${project.version}/${project.name}-${directorySubname}-${project.version}.module")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (directorySubname == "kotlinMultiplatform" && it.getName() == "pom-default.xml") {
|
||||||
|
it.setPath("${project.name}/${project.version}/${project.name}-${project.version}.pom")
|
||||||
|
} else {
|
||||||
|
it.exclude()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
into "${project.group}".replace(".", "/")
|
||||||
|
}
|
||||||
|
pkg {
|
||||||
|
repo = "StandardRepository"
|
||||||
|
name = "${project.name}"
|
||||||
|
vcsUrl = "https://github.com/InsanusMokrassar/TelegramBotAPI"
|
||||||
|
licenses = ["Apache-2.0"]
|
||||||
|
version {
|
||||||
|
name = "${project.version}"
|
||||||
|
released = new Date()
|
||||||
|
vcsTag = "${project.version}"
|
||||||
|
gpg {
|
||||||
|
sign = true
|
||||||
|
passphrase = project.hasProperty('signing.gnupg.passphrase') ? project.property('signing.gnupg.passphrase') : System.getenv('signing.gnupg.passphrase')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bintrayUpload.doFirst {
|
||||||
|
publications = publishing.publications.collect {
|
||||||
|
if (it.name.contains('kotlinMultiplatform')) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
it.name
|
||||||
|
}
|
||||||
|
} - null
|
||||||
|
}
|
||||||
|
|
||||||
|
bintrayUpload.dependsOn publishToMavenLocal
|
||||||
@@ -55,14 +55,22 @@ compile "com.github.insanusmokrassar:TelegramBotAPI-extensions-api:$telegrambota
|
|||||||
## Example of usage and comparison with `TelegramBotAPI`
|
## Example of usage and comparison with `TelegramBotAPI`
|
||||||
|
|
||||||
Here presented review table for comparison of api from original [TelegramBotAPI](../TelegramBotAPI/README.md#Requests)
|
Here presented review table for comparison of api from original [TelegramBotAPI](../TelegramBotAPI/README.md#Requests)
|
||||||
and extensions-api library:
|
and extensions-api library. First of all, this library allow to create bot instance in a new way:
|
||||||
|
|
||||||
In all examples supposed that you have created bot with next approximate lines:
|
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
val bot: RequestsExecutor = ...
|
val bot = telegramBot("IT IS YOUR TOKEN")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
There are a lot of signature for this. For example, you can create bot with next code:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val bot = telegramBot("IT IS YOUR TOKEN") {
|
||||||
|
proxy = ProxyBuilder.socks("127.0.0.1", 1080)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In all examples supposed that you have created bot.
|
||||||
|
|
||||||
| TelegramBotAPI | TelegramBotAPI-extensions-api |
|
| TelegramBotAPI | TelegramBotAPI-extensions-api |
|
||||||
|----------------|-------------------------------|
|
|----------------|-------------------------------|
|
||||||
| bot.execute(GetMe) | bot.getMe() |
|
| bot.execute(GetMe) | bot.getMe() |
|
||||||
@@ -70,6 +78,10 @@ val bot: RequestsExecutor = ...
|
|||||||
|
|
||||||
## Updates
|
## Updates
|
||||||
|
|
||||||
|
**Currently, these paragraphs almost outdated due to the fact that extensions for listening of updates and webhooks were
|
||||||
|
replaced into `TelegramBotAPI-extensions-utils`. But, most part of information below is correct with small fixes and
|
||||||
|
adding of `TelegramBotAPI-extensions-utils` dependency.**
|
||||||
|
|
||||||
Usually, it is more comfortable to use filter object to get separated types of updates:
|
Usually, it is more comfortable to use filter object to get separated types of updates:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ kotlin {
|
|||||||
if ((project.hasProperty('RELEASE_MODE') && project.property('RELEASE_MODE') == "true") || System.getenv('RELEASE_MODE') == "true") {
|
if ((project.hasProperty('RELEASE_MODE') && project.property('RELEASE_MODE') == "true") || System.getenv('RELEASE_MODE') == "true") {
|
||||||
api "${project.group}:TelegramBotAPI:$library_version"
|
api "${project.group}:TelegramBotAPI:$library_version"
|
||||||
} else {
|
} else {
|
||||||
implementation project(":TelegramBotAPI")
|
api project(":TelegramBotAPI")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,37 +20,33 @@ publishing {
|
|||||||
publications.all {
|
publications.all {
|
||||||
artifact javadocsJar
|
artifact javadocsJar
|
||||||
|
|
||||||
pom.withXml {
|
pom {
|
||||||
asNode().children().last() + {
|
description = "API extensions which provide work with RequestsExecutor of TelegramBotAPI almost like it is described in original Telegram Bot API reference"
|
||||||
resolveStrategy = Closure.DELEGATE_FIRST
|
name = "Telegram Bot API Extensions for API"
|
||||||
|
url = "https://insanusmokrassar.github.io/TelegramBotAPI/TelegramBotAPI-extensions-api"
|
||||||
|
|
||||||
description "API extensions which provide work with RequestsExecutor of TelegramBotAPI almost like it is described in original Telegram Bot API reference"
|
scm {
|
||||||
name "Telegram Bot API Extensions for API"
|
developerConnection = "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
||||||
url "https://insanusmokrassar.github.io/TelegramBotAPI"
|
url = "https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
||||||
|
}
|
||||||
|
|
||||||
scm {
|
developers {
|
||||||
developerConnection "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
|
||||||
url "https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
developer {
|
||||||
}
|
id = "InsanusMokrassar"
|
||||||
|
name = "Ovsiannikov Aleksei"
|
||||||
|
email = "ovsyannikov.alexey95@gmail.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
developers {
|
licenses {
|
||||||
|
|
||||||
developer {
|
license {
|
||||||
id "InsanusMokrassar"
|
name = "Apache Software License 2.0"
|
||||||
name "Ovsiannikov Aleksei"
|
url = "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
|
||||||
email "ovsyannikov.alexey95@gmail.com"
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
licenses {
|
|
||||||
|
|
||||||
license {
|
|
||||||
name "Apache Software License 2.0"
|
|
||||||
url "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"bintrayConfig":{"repo":"StandardRepository","packageName":"${project.name}","packageVcs":"https://github.com/InsanusMokrassar/TelegramBotAPI"},"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"}],"mavenConfig":{"name":"Telegram Bot API Extensions for API","description":"API extensions which provide work with RequestsExecutor of TelegramBotAPI almost like it is described in original Telegram Bot API reference","url":"https://insanusmokrassar.github.io/TelegramBotAPI","vcsUrl":"https://github.com/insanusmokrassar/TelegramBotAPI.git","developers":[{"id":"InsanusMokrassar","name":"Ovsiannikov Aleksei","eMail":"ovsyannikov.alexey95@gmail.com"}]},"type":"Multiplatform"}
|
{"bintrayConfig":{"repo":"StandardRepository","packageName":"${project.name}","packageVcs":"https://github.com/InsanusMokrassar/TelegramBotAPI"},"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"}],"mavenConfig":{"name":"Telegram Bot API Extensions for API","description":"API extensions which provide work with RequestsExecutor of TelegramBotAPI almost like it is described in original Telegram Bot API reference","url":"https://insanusmokrassar.github.io/TelegramBotAPI/TelegramBotAPI-extensions-api","vcsUrl":"https://github.com/insanusmokrassar/TelegramBotAPI.git","developers":[{"id":"InsanusMokrassar","name":"Ovsiannikov Aleksei","eMail":"ovsyannikov.alexey95@gmail.com"}]},"type":"Multiplatform"}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.extensions.api
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.bot.RequestsExecutor
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.TelegramAPIUrlsKeeper
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import io.ktor.client.HttpClientConfig
|
||||||
|
import io.ktor.client.engine.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param proxy Standard ktor [ProxyConfig]
|
||||||
|
* @param ktorClientEngine Engine like [io.ktor.client.engine.cio.CIO]
|
||||||
|
* @param ktorClientConfig Config block for preconfiguring of bot [HttpClient]
|
||||||
|
*/
|
||||||
|
data class BotBuilder internal constructor(
|
||||||
|
var proxy: ProxyConfig? = null,
|
||||||
|
@Deprecated("ktorClientEngineFactory parameter will be used preferable. In future this parameter will be removed")
|
||||||
|
var ktorClientEngine: HttpClientEngine? = null,
|
||||||
|
var ktorClientEngineFactory: HttpClientEngineFactory<out HttpClientEngineConfig>? = null,
|
||||||
|
var ktorClientConfig: (HttpClientConfig<*>.() -> Unit) ? = null
|
||||||
|
) {
|
||||||
|
internal fun createHttpClient(): HttpClient = ktorClientEngineFactory ?.let {
|
||||||
|
HttpClient(
|
||||||
|
it.create {
|
||||||
|
this@create.proxy = this@BotBuilder.proxy ?: this@create.proxy
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
ktorClientConfig ?.let { it() }
|
||||||
|
}
|
||||||
|
} ?: ktorClientEngine ?.let { engine ->
|
||||||
|
HttpClient(engine) {
|
||||||
|
ktorClientConfig ?.let { it() }
|
||||||
|
engine {
|
||||||
|
this@engine.proxy = this@BotBuilder.proxy ?: this@engine.proxy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} ?: HttpClient {
|
||||||
|
ktorClientConfig ?.let { it() }
|
||||||
|
engine {
|
||||||
|
this@engine.proxy = this@BotBuilder.proxy ?: this@engine.proxy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Created by [telegramBotWithCustomClientConfig] function [RequestsExecutor]. This executor will be preconfigured using [token] and
|
||||||
|
* [block]
|
||||||
|
*/
|
||||||
|
fun telegramBot(
|
||||||
|
token: String,
|
||||||
|
block: BotBuilder.() -> Unit
|
||||||
|
): RequestsExecutor = telegramBot(
|
||||||
|
TelegramAPIUrlsKeeper(token),
|
||||||
|
BotBuilder().apply(block).createHttpClient()
|
||||||
|
)
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.extensions.api
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor.KtorRequestsExecutor
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.bot.RequestsExecutor
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.TelegramAPIUrlsKeeper
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import io.ktor.client.HttpClientConfig
|
||||||
|
import io.ktor.client.engine.HttpClientEngine
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to create bot using bot [urlsKeeper] and already prepared [client]
|
||||||
|
*/
|
||||||
|
fun telegramBot(
|
||||||
|
urlsKeeper: TelegramAPIUrlsKeeper,
|
||||||
|
client: HttpClient
|
||||||
|
): RequestsExecutor = KtorRequestsExecutor(
|
||||||
|
urlsKeeper,
|
||||||
|
client
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to create bot using bot [urlsKeeper] and specify [HttpClientEngine] by passing [clientEngine] param and optionally
|
||||||
|
* configure [HttpClient] using [clientConfig]
|
||||||
|
*/
|
||||||
|
fun telegramBotWithCustomClientConfig(
|
||||||
|
urlsKeeper: TelegramAPIUrlsKeeper,
|
||||||
|
clientEngine: HttpClientEngine,
|
||||||
|
clientConfig: HttpClientConfig<*>.() -> Unit = {}
|
||||||
|
): RequestsExecutor = telegramBot(
|
||||||
|
urlsKeeper,
|
||||||
|
HttpClient(clientEngine, clientConfig)
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to create bot using bot [urlsKeeper] and optionally configure [HttpClient] using [clientConfig]
|
||||||
|
*/
|
||||||
|
fun telegramBotWithCustomClientConfig(
|
||||||
|
urlsKeeper: TelegramAPIUrlsKeeper,
|
||||||
|
clientConfig: HttpClientConfig<*>.() -> Unit = {}
|
||||||
|
): RequestsExecutor = telegramBot(
|
||||||
|
urlsKeeper,
|
||||||
|
HttpClient(clientConfig)
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to create bot using bot [token]
|
||||||
|
*/
|
||||||
|
fun telegramBot(
|
||||||
|
token: String
|
||||||
|
): RequestsExecutor = telegramBotWithCustomClientConfig(TelegramAPIUrlsKeeper(token))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to create bot using bot [token] and already prepared [client]
|
||||||
|
*/
|
||||||
|
fun telegramBot(
|
||||||
|
token: String,
|
||||||
|
client: HttpClient
|
||||||
|
): RequestsExecutor = telegramBot(TelegramAPIUrlsKeeper(token), client)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to create bot using bot [token] and configure [HttpClient] using [clientConfig]
|
||||||
|
*/
|
||||||
|
fun telegramBotWithCustomClientConfig(
|
||||||
|
token: String,
|
||||||
|
clientConfig: HttpClientConfig<*>.() -> Unit
|
||||||
|
): RequestsExecutor = telegramBotWithCustomClientConfig(TelegramAPIUrlsKeeper(token), clientConfig)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to create bot using bot [token] and specify [HttpClientEngine] by passing [clientEngine] param and optionally
|
||||||
|
* configure [HttpClient] using [clientConfig]
|
||||||
|
*/
|
||||||
|
fun telegramBot(
|
||||||
|
token: String,
|
||||||
|
clientEngine: HttpClientEngine,
|
||||||
|
clientConfig: HttpClientConfig<*>.() -> Unit = {}
|
||||||
|
): RequestsExecutor = telegramBotWithCustomClientConfig(TelegramAPIUrlsKeeper(token), clientEngine, clientConfig)
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.extensions.api
|
||||||
|
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
|
@Suppress("EXPERIMENTAL_API_USAGE")
|
||||||
|
internal val nonstrictJsonFormat = Json {
|
||||||
|
isLenient = true
|
||||||
|
ignoreUnknownKeys = true
|
||||||
|
serializeSpecialFloatingPointValues = true
|
||||||
|
useArrayPolymorphism = true
|
||||||
|
}
|
||||||
@@ -7,3 +7,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.BotCommand
|
|||||||
suspend fun RequestsExecutor.setMyCommands(
|
suspend fun RequestsExecutor.setMyCommands(
|
||||||
commands: List<BotCommand>
|
commands: List<BotCommand>
|
||||||
) = execute(SetMyCommands(commands))
|
) = execute(SetMyCommands(commands))
|
||||||
|
|
||||||
|
suspend fun RequestsExecutor.setMyCommands(
|
||||||
|
vararg commands: BotCommand
|
||||||
|
) = setMyCommands(commands.toList())
|
||||||
|
|||||||
@@ -2,8 +2,12 @@ package com.github.insanusmokrassar.TelegramBotAPI.extensions.api.chat.get
|
|||||||
|
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.bot.RequestsExecutor
|
import com.github.insanusmokrassar.TelegramBotAPI.bot.RequestsExecutor
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.requests.chat.get.GetChat
|
import com.github.insanusmokrassar.TelegramBotAPI.requests.chat.get.GetChat
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.ChatIdentifier
|
import com.github.insanusmokrassar.TelegramBotAPI.types.*
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.Chat
|
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.extended.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.PreviewFeature
|
||||||
|
|
||||||
suspend fun RequestsExecutor.getChat(
|
suspend fun RequestsExecutor.getChat(
|
||||||
chatId: ChatIdentifier
|
chatId: ChatIdentifier
|
||||||
@@ -12,3 +16,117 @@ suspend fun RequestsExecutor.getChat(
|
|||||||
suspend fun RequestsExecutor.getChat(
|
suspend fun RequestsExecutor.getChat(
|
||||||
chat: Chat
|
chat: Chat
|
||||||
) = getChat(chat.id)
|
) = getChat(chat.id)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will cast incoming [com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat] to a
|
||||||
|
* [ExtendedPublicChat] with unsafe operator "as"
|
||||||
|
*
|
||||||
|
* @throws ClassCastException
|
||||||
|
*/
|
||||||
|
@PreviewFeature
|
||||||
|
suspend fun RequestsExecutor.getChat(
|
||||||
|
chat: PublicChat
|
||||||
|
) = getChat(chat.id) as ExtendedPublicChat
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will cast incoming [com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat] to a
|
||||||
|
* [ExtendedChannelChat] with unsafe operator "as"
|
||||||
|
*
|
||||||
|
* @throws ClassCastException
|
||||||
|
*/
|
||||||
|
@PreviewFeature
|
||||||
|
suspend fun RequestsExecutor.getChat(
|
||||||
|
chat: ChannelChat
|
||||||
|
) = getChat(chat.id) as ExtendedChannelChat
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will cast incoming [com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat] to a
|
||||||
|
* [ExtendedChannelChatImpl] with unsafe operator "as"
|
||||||
|
*
|
||||||
|
* @throws ClassCastException
|
||||||
|
*/
|
||||||
|
@PreviewFeature
|
||||||
|
suspend fun RequestsExecutor.getChat(
|
||||||
|
chat: ChannelChatImpl
|
||||||
|
) = getChat(chat.id) as ExtendedChannelChatImpl
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will cast incoming [com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat] to a
|
||||||
|
* [ExtendedGroupChat] with unsafe operator "as"
|
||||||
|
*
|
||||||
|
* @throws ClassCastException
|
||||||
|
*/
|
||||||
|
@PreviewFeature
|
||||||
|
suspend fun RequestsExecutor.getChat(
|
||||||
|
chat: GroupChat
|
||||||
|
) = getChat(chat.id) as ExtendedGroupChat
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will cast incoming [com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat] to a
|
||||||
|
* [ExtendedGroupChatImpl] with unsafe operator "as"
|
||||||
|
*
|
||||||
|
* @throws ClassCastException
|
||||||
|
*/
|
||||||
|
@PreviewFeature
|
||||||
|
suspend fun RequestsExecutor.getChat(
|
||||||
|
chat: GroupChatImpl
|
||||||
|
) = getChat(chat.id) as ExtendedGroupChatImpl
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will cast incoming [com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat] to a
|
||||||
|
* [ExtendedSupergroupChat] with unsafe operator "as"
|
||||||
|
*
|
||||||
|
* @throws ClassCastException
|
||||||
|
*/
|
||||||
|
@PreviewFeature
|
||||||
|
suspend fun RequestsExecutor.getChat(
|
||||||
|
chat: SupergroupChat
|
||||||
|
) = getChat(chat.id) as ExtendedSupergroupChat
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will cast incoming [com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat] to a
|
||||||
|
* [ExtendedSupergroupChatImpl] with unsafe operator "as"
|
||||||
|
*
|
||||||
|
* @throws ClassCastException
|
||||||
|
*/
|
||||||
|
@PreviewFeature
|
||||||
|
suspend fun RequestsExecutor.getChat(
|
||||||
|
chat: SupergroupChatImpl
|
||||||
|
) = getChat(chat.id) as ExtendedSupergroupChatImpl
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will cast incoming [com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat] to a
|
||||||
|
* [ExtendedPrivateChat] with unsafe operator "as"
|
||||||
|
*
|
||||||
|
* @throws ClassCastException
|
||||||
|
*/
|
||||||
|
@PreviewFeature
|
||||||
|
suspend fun RequestsExecutor.getChat(
|
||||||
|
chat: PrivateChat
|
||||||
|
) = getChat(chat.id) as ExtendedPrivateChat
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will cast incoming [com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat] to a
|
||||||
|
* [ExtendedPrivateChatImpl] with unsafe operator "as"
|
||||||
|
*
|
||||||
|
* @throws ClassCastException
|
||||||
|
*/
|
||||||
|
@PreviewFeature
|
||||||
|
suspend fun RequestsExecutor.getChat(
|
||||||
|
chat: PrivateChatImpl
|
||||||
|
) = getChat(chat.id) as ExtendedPrivateChatImpl
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will cast incoming [com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat] to a
|
||||||
|
* [ExtendedUser] with unsafe operator "as"
|
||||||
|
*
|
||||||
|
* @throws ClassCastException
|
||||||
|
*/
|
||||||
|
@PreviewFeature
|
||||||
|
suspend fun RequestsExecutor.getChat(
|
||||||
|
chat: CommonUser
|
||||||
|
) = getChat(chat.id) as ExtendedUser
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.requests.send.SendVenue
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.*
|
import com.github.insanusmokrassar.TelegramBotAPI.types.*
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
|
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.Chat
|
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.Chat
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.venue.Venue
|
||||||
|
|
||||||
suspend fun RequestsExecutor.sendVenue(
|
suspend fun RequestsExecutor.sendVenue(
|
||||||
chatId: ChatIdentifier,
|
chatId: ChatIdentifier,
|
||||||
@@ -36,6 +37,32 @@ suspend fun RequestsExecutor.sendVenue(
|
|||||||
chat.id, latitude, longitude, title, address, foursquareId, disableNotification, replyToMessageId, replyMarkup
|
chat.id, latitude, longitude, title, address, foursquareId, disableNotification, replyToMessageId, replyMarkup
|
||||||
)
|
)
|
||||||
|
|
||||||
|
suspend fun RequestsExecutor.sendVenue(
|
||||||
|
chatId: ChatIdentifier,
|
||||||
|
location: Location,
|
||||||
|
title: String,
|
||||||
|
address: String,
|
||||||
|
foursquareId: String? = null,
|
||||||
|
disableNotification: Boolean = false,
|
||||||
|
replyToMessageId: MessageIdentifier? = null,
|
||||||
|
replyMarkup: KeyboardMarkup? = null
|
||||||
|
) = sendVenue(
|
||||||
|
chatId, location.latitude, location.longitude, title, address, foursquareId, disableNotification, replyToMessageId, replyMarkup
|
||||||
|
)
|
||||||
|
|
||||||
|
suspend fun RequestsExecutor.sendVenue(
|
||||||
|
chat: Chat,
|
||||||
|
location: Location,
|
||||||
|
title: String,
|
||||||
|
address: String,
|
||||||
|
foursquareId: String? = null,
|
||||||
|
disableNotification: Boolean = false,
|
||||||
|
replyToMessageId: MessageIdentifier? = null,
|
||||||
|
replyMarkup: KeyboardMarkup? = null
|
||||||
|
) = sendVenue(
|
||||||
|
chat.id, location.latitude, location.longitude, title, address, foursquareId, disableNotification, replyToMessageId, replyMarkup
|
||||||
|
)
|
||||||
|
|
||||||
suspend fun RequestsExecutor.sendVenue(
|
suspend fun RequestsExecutor.sendVenue(
|
||||||
chatId: ChatIdentifier,
|
chatId: ChatIdentifier,
|
||||||
venue: Venue,
|
venue: Venue,
|
||||||
|
|||||||
@@ -10,14 +10,14 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.update.*
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates.*
|
import com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates.*
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update
|
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.*
|
import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.*
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.utils.PreviewFeature
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.*
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.utils.handleSafely
|
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
|
|
||||||
|
@Deprecated("Replaced and renamed in TelegramBotAPI-extensions-utils")
|
||||||
fun RequestsExecutor.startGettingOfUpdates(
|
fun RequestsExecutor.startGettingOfUpdates(
|
||||||
timeoutSeconds: Seconds = 30,
|
timeoutSeconds: Seconds = 30,
|
||||||
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
||||||
exceptionsHandler: (suspend (Exception) -> Unit)? = null,
|
exceptionsHandler: (ExceptionHandler<Unit>)? = null,
|
||||||
allowedUpdates: List<String>? = null,
|
allowedUpdates: List<String>? = null,
|
||||||
updatesReceiver: UpdateReceiver<Update>
|
updatesReceiver: UpdateReceiver<Update>
|
||||||
): Job = scope.launch {
|
): Job = scope.launch {
|
||||||
@@ -68,18 +68,22 @@ fun RequestsExecutor.startGettingOfUpdates(
|
|||||||
* [kotlinx.coroutines.flow.Flow.collect] on one of [FlowsUpdatesFilter] flows. To avoid it, you can pass
|
* [kotlinx.coroutines.flow.Flow.collect] on one of [FlowsUpdatesFilter] flows. To avoid it, you can pass
|
||||||
* [flowUpdatesPreset] lambda - it will be called BEFORE starting updates getting
|
* [flowUpdatesPreset] lambda - it will be called BEFORE starting updates getting
|
||||||
*/
|
*/
|
||||||
|
@FlowPreview
|
||||||
@PreviewFeature
|
@PreviewFeature
|
||||||
|
@Suppress("unused")
|
||||||
|
@Deprecated("Replaced and renamed in TelegramBotAPI-extensions-utils")
|
||||||
fun RequestsExecutor.startGettingFlowsUpdates(
|
fun RequestsExecutor.startGettingFlowsUpdates(
|
||||||
timeoutSeconds: Seconds = 30,
|
timeoutSeconds: Seconds = 30,
|
||||||
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
||||||
exceptionsHandler: (suspend (Exception) -> Unit)? = null,
|
exceptionsHandler: (suspend (Exception) -> Unit)? = null,
|
||||||
flowsUpdatesFilterUpdatesKeeperCount: Int = 64,
|
flowsUpdatesFilterUpdatesKeeperCount: Int = 100,
|
||||||
flowUpdatesPreset: FlowsUpdatesFilter.() -> Unit = {}
|
flowUpdatesPreset: FlowsUpdatesFilter.() -> Unit = {}
|
||||||
): FlowsUpdatesFilter = FlowsUpdatesFilter(flowsUpdatesFilterUpdatesKeeperCount).apply {
|
): FlowsUpdatesFilter = FlowsUpdatesFilter(flowsUpdatesFilterUpdatesKeeperCount).apply {
|
||||||
flowUpdatesPreset()
|
flowUpdatesPreset()
|
||||||
startGettingOfUpdates(timeoutSeconds, scope, exceptionsHandler, allowedUpdates, asUpdateReceiver)
|
startGettingOfUpdates(timeoutSeconds, scope, exceptionsHandler, allowedUpdates, asUpdateReceiver)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("Replaced and renamed in TelegramBotAPI-extensions-utils")
|
||||||
fun RequestsExecutor.startGettingOfUpdates(
|
fun RequestsExecutor.startGettingOfUpdates(
|
||||||
updatesFilter: UpdatesFilter,
|
updatesFilter: UpdatesFilter,
|
||||||
timeoutSeconds: Seconds = 30,
|
timeoutSeconds: Seconds = 30,
|
||||||
@@ -93,6 +97,7 @@ fun RequestsExecutor.startGettingOfUpdates(
|
|||||||
updatesFilter.asUpdateReceiver
|
updatesFilter.asUpdateReceiver
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Deprecated("Replaced and renamed in TelegramBotAPI-extensions-utils")
|
||||||
fun RequestsExecutor.startGettingOfUpdates(
|
fun RequestsExecutor.startGettingOfUpdates(
|
||||||
messageCallback: UpdateReceiver<MessageUpdate>? = null,
|
messageCallback: UpdateReceiver<MessageUpdate>? = null,
|
||||||
messageMediaGroupCallback: UpdateReceiver<MessageMediaGroupUpdate>? = null,
|
messageMediaGroupCallback: UpdateReceiver<MessageMediaGroupUpdate>? = null,
|
||||||
@@ -137,6 +142,8 @@ fun RequestsExecutor.startGettingOfUpdates(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
@Deprecated("Replaced and renamed in TelegramBotAPI-extensions-utils")
|
||||||
fun RequestsExecutor.startGettingOfUpdates(
|
fun RequestsExecutor.startGettingOfUpdates(
|
||||||
messageCallback: UpdateReceiver<MessageUpdate>? = null,
|
messageCallback: UpdateReceiver<MessageUpdate>? = null,
|
||||||
mediaGroupCallback: UpdateReceiver<MediaGroupUpdate>? = null,
|
mediaGroupCallback: UpdateReceiver<MediaGroupUpdate>? = null,
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.extensions.api.utils
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.extensions.api.InternalUtils.convertWithMediaGroupUpdates
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.MediaGroupMessage
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.BaseMessageUpdate
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.UpdateReceiver
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.extensions.accumulateByKey
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.channels.Channel
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create [UpdateReceiver] object which will correctly accumulate updates and send into output updates which INCLUDE
|
||||||
|
* [com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates.MediaGroupUpdate]s.
|
||||||
|
*
|
||||||
|
* @see UpdateReceiver
|
||||||
|
*/
|
||||||
|
fun CoroutineScope.updateHandlerWithMediaGroupsAdaptation(
|
||||||
|
output: UpdateReceiver<Update>,
|
||||||
|
mediaGroupsDebounceMillis: Long = 1000L
|
||||||
|
): UpdateReceiver<Update> {
|
||||||
|
val updatesChannel = Channel<Update>(Channel.UNLIMITED)
|
||||||
|
val mediaGroupChannel = Channel<Pair<String, BaseMessageUpdate>>(Channel.UNLIMITED)
|
||||||
|
val mediaGroupAccumulatedChannel = mediaGroupChannel.accumulateByKey(
|
||||||
|
mediaGroupsDebounceMillis,
|
||||||
|
scope = this
|
||||||
|
)
|
||||||
|
|
||||||
|
launch {
|
||||||
|
launch {
|
||||||
|
for (update in updatesChannel) {
|
||||||
|
when (val data = update.data) {
|
||||||
|
is MediaGroupMessage -> mediaGroupChannel.send("${data.mediaGroupId}${update::class.simpleName}" to update as BaseMessageUpdate)
|
||||||
|
else -> output(update)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
launch {
|
||||||
|
for ((_, mediaGroup) in mediaGroupAccumulatedChannel) {
|
||||||
|
mediaGroup.convertWithMediaGroupUpdates().forEach {
|
||||||
|
output(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { updatesChannel.send(it) }
|
||||||
|
}
|
||||||
@@ -5,6 +5,22 @@ import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.FileId
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.MultipartFile
|
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.MultipartFile
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.requests.webhook.SetWebhook
|
import com.github.insanusmokrassar.TelegramBotAPI.requests.webhook.SetWebhook
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this method to send information about webhook (like [url])
|
||||||
|
*/
|
||||||
|
suspend fun RequestsExecutor.setWebhookInfo(
|
||||||
|
url: String,
|
||||||
|
maxAllowedConnections: Int? = null,
|
||||||
|
allowedUpdates: List<String>? = null
|
||||||
|
) = execute(
|
||||||
|
SetWebhook(
|
||||||
|
url, maxAllowedConnections, allowedUpdates
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this method to send information about webhook (like [url] and [certificate])
|
||||||
|
*/
|
||||||
suspend fun RequestsExecutor.setWebhookInfo(
|
suspend fun RequestsExecutor.setWebhookInfo(
|
||||||
url: String,
|
url: String,
|
||||||
certificate: FileId,
|
certificate: FileId,
|
||||||
@@ -16,6 +32,9 @@ suspend fun RequestsExecutor.setWebhookInfo(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this method to send information about webhook (like [url] and [certificate])
|
||||||
|
*/
|
||||||
suspend fun RequestsExecutor.setWebhookInfo(
|
suspend fun RequestsExecutor.setWebhookInfo(
|
||||||
url: String,
|
url: String,
|
||||||
certificate: MultipartFile,
|
certificate: MultipartFile,
|
||||||
@@ -1,5 +1,23 @@
|
|||||||
# TelegramBotAPI Util Extensions
|
# TelegramBotAPI Util Extensions
|
||||||
|
|
||||||
|
- [TelegramBotAPI Util Extensions](#telegrambotapi-util--extensions)
|
||||||
|
* [What is it?](#what-is-it-)
|
||||||
|
* [How to implement library?](#how-to-implement-library-)
|
||||||
|
+ [Maven](#maven)
|
||||||
|
+ [Gradle](#gradle)
|
||||||
|
* [How to use?](#how-to-use-)
|
||||||
|
+ [Updates](#updates)
|
||||||
|
- [Long polling](#long-polling)
|
||||||
|
- [WebHooks (currently JVM-only)](#webhooks--currently-jvm-only-)
|
||||||
|
+ [Filters](#filters)
|
||||||
|
- [Sent messages](#sent-messages)
|
||||||
|
* [Common messages](#common-messages)
|
||||||
|
* [Chat actions](#chat-actions)
|
||||||
|
+ [Shortcuts](#shortcuts)
|
||||||
|
- [ScheduledCloseInfo](#scheduledcloseinfo)
|
||||||
|
|
||||||
|
<small><i><a href='http://ecotrust-canada.github.io/markdown-toc/'>Table of contents generated with markdown-toc</a></i></small>
|
||||||
|
|
||||||
[ ](https://bintray.com/insanusmokrassar/StandardRepository/TelegramBotAPI-extensions-utils/_latestVersion)
|
[ ](https://bintray.com/insanusmokrassar/StandardRepository/TelegramBotAPI-extensions-utils/_latestVersion)
|
||||||
[](https://maven-badges.herokuapp.com/maven-central/com.github.insanusmokrassar/TelegramBotAPI-extensions-utils)
|
[](https://maven-badges.herokuapp.com/maven-central/com.github.insanusmokrassar/TelegramBotAPI-extensions-utils)
|
||||||
|
|
||||||
@@ -60,31 +78,190 @@ val filter = FlowsUpdatesFilter(64)
|
|||||||
Alternative way to use the things below:
|
Alternative way to use the things below:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
val filter = bot.startGettingUpdates(
|
val filter = bot.startGettingFlowsUpdatesByLongPolling(
|
||||||
scope = CoroutineScope(Dispatchers.Default)
|
scope = CoroutineScope(Dispatchers.Default)
|
||||||
) {
|
) {
|
||||||
// place code from examples here with replacing of `filter` by `this`
|
// place code from examples here with replacing of `filter` by `this`
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Getting of only text incoming messages
|
### Updates
|
||||||
|
|
||||||
|
As mentioned in [Telegram Bot API reference](https://core.telegram.org/bots/api#getting-updates), there are two ways for
|
||||||
|
updates retrieving:
|
||||||
|
|
||||||
|
* Webhooks
|
||||||
|
* Long Polling
|
||||||
|
|
||||||
|
Both of them you could use in your project using [TelegramBotAPI](../TelegramBotAPI/README.md), but here there are
|
||||||
|
several useful extensions for both of them.
|
||||||
|
|
||||||
|
Anyway, in both of ways it will be useful to know that it is possible to create `UpdateReceiver` object using function
|
||||||
|
`flowsUpdatesFilter`:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
filter.asContentMessagesFlow().onlyTextContentMessages().onEach {
|
val internalChannelsSizes = 128
|
||||||
|
flowsUpdatesFilter(internalChannelsSizes/* default is 64 */) {
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Long polling
|
||||||
|
|
||||||
|
The most simple way is Long Polling and one of the usages was mentioned above:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val filter = bot.startGettingFlowsUpdatesByLongPolling(
|
||||||
|
scope = CoroutineScope(Dispatchers.Default)
|
||||||
|
) {
|
||||||
|
// place code from examples here with replacing of `filter` by `this`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Extension `startGettingFlowsUpdatesByLongPolling` was used in this example, but there are a lot of variations of
|
||||||
|
`startGettingOfUpdatesByLongPolling` and others for getting the same result. Usually, it is supposed that you already
|
||||||
|
have created `filter` object (or something like this) and will pass it into extension:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val filter = FlowsUpdatesFilter(64)
|
||||||
|
bot.startGettingOfUpdatesByLongPolling(
|
||||||
|
filter
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
But also there are extensions which allow to pass lambdas directly:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
bot.startGettingOfUpdatesByLongPolling(
|
||||||
|
{
|
||||||
|
println("Received message update: $it")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Anyway, it is strictly recommended to pass your `CoroutineScope` object to this method at least for more comfortable
|
||||||
|
management of updates.
|
||||||
|
|
||||||
|
#### WebHooks (currently JVM-only)
|
||||||
|
|
||||||
|
For webhooks there are less number of functions and extensions than for Long Polling (but it is still fully automated):
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
startListenWebhooks(
|
||||||
|
8081,
|
||||||
|
CIO // require to implement this engine dependency
|
||||||
|
) {
|
||||||
|
// here will be all updates one by one in $it
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Besides, there are two additional opportunities:
|
||||||
|
|
||||||
|
* Extension `Route#includeWebhookHandlingInRoute`, which allow you to include webhook processing inside your ktor
|
||||||
|
application without creating of new one server (as it is happening in `startListenWebhooks`)
|
||||||
|
* Extension `RequestsExecutor#setWebhookInfoAndStartListenWebhooks`. It is allow to set up full server (in fact, with
|
||||||
|
`startListenWebhooks`), but also send `SetWebhook` request before and check that it was successful
|
||||||
|
|
||||||
|
### Filters
|
||||||
|
|
||||||
|
There are several filters for flows.
|
||||||
|
|
||||||
|
#### Updates
|
||||||
|
|
||||||
|
In the next table it is supposed that you are using some `Flow` with type from `Base type of update` and apply
|
||||||
|
extension `Extension` and will get `Flow` with type from `Result type of update` column.
|
||||||
|
|
||||||
|
| Base type of update | Extension | Result type of update |
|
||||||
|
| ------------------- | --------- | --------------------- |
|
||||||
|
| `Update` | `onlyBaseMessageUpdates` | `BaseMessageUpdate` |
|
||||||
|
| | | |
|
||||||
|
| `BaseMessageUpdate` | `onlySentMessageUpdates` | `BaseSentMessageUpdate` |
|
||||||
|
| `BaseMessageUpdate` | `onlyEditMessageUpdates` | `BaseEditMessageUpdate` |
|
||||||
|
| `BaseMessageUpdate` | `onlyMediaGroupsUpdates` | `MediaGroupUpdate` |
|
||||||
|
| | | |
|
||||||
|
| `MediaGroupUpdate` | `onlySentMediaGroupUpdates` | `SentMediaGroupUpdate` |
|
||||||
|
| `MediaGroupUpdate` | `onlyEditMediaGroupUpdates` | `EditMediaGroupUpdate` |
|
||||||
|
|
||||||
|
All of these extensions was made for more simple work with the others:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val flow: Flow<BaseMessageUpdate> = ...; // here we are getting flow from somewhere,
|
||||||
|
// for example, FlowsUpdatesFilter#messageFlow
|
||||||
|
flow.onlySentMessageUpdates().filterExactCommands(Regex("start"))
|
||||||
|
```
|
||||||
|
|
||||||
|
Here we have used filter `filterExactCommands` which will pass only `ContentMessage` with only one command `start`
|
||||||
|
|
||||||
|
#### Sent messages
|
||||||
|
|
||||||
|
All sent messages can be filtered for three types:
|
||||||
|
|
||||||
|
| Type | Description | Flow extension |
|
||||||
|
|:---- |:----------- |:-------------- |
|
||||||
|
| Common messages | Simple messages with text, media, location, etc. | `asContentMessagesFlow` |
|
||||||
|
| Chat actions | New chat member, rename of chat, etc. | `asChatEventsFlow` |
|
||||||
|
| Unknown events | Any other messages, that contain unsupported data | `asUnknownMessagesFlow` |
|
||||||
|
|
||||||
|
##### Common messages
|
||||||
|
|
||||||
|
Unfortunately, due to the erasing of generic types, when you are using `asContentMessagesFlow` you will retrieve
|
||||||
|
data with type `ContentMessage<*>`. For correct filtering of content type for retrieved objects, was created special
|
||||||
|
filters:
|
||||||
|
|
||||||
|
| Content type | Result type | Flow extension |
|
||||||
|
|:---- |:----------- |:-------------- |
|
||||||
|
| Animation | `ContentMessage<AnimationContent>`| `onlyAnimationContentMessages` |
|
||||||
|
| Audio | `ContentMessage<AudioContent>` | `onlyAudioContentMessages` |
|
||||||
|
| Contact | `ContentMessage<ContactContent>` | `onlyContactContentMessages` |
|
||||||
|
| Dice | `ContentMessage<DiceContent>` | `onlyDiceContentMessages` |
|
||||||
|
| Document | `ContentMessage<DocumentContent>` | `onlyDocumentContentMessages` |
|
||||||
|
| Game | `ContentMessage<GameContent>` | `onlyGameContentMessages` |
|
||||||
|
| Invoice | `ContentMessage<InvoiceContent>` | `onlyInvoiceContentMessages` |
|
||||||
|
| Location | `ContentMessage<LocationContent>` | `onlyLocationContentMessages` |
|
||||||
|
| Photo | `ContentMessage<PhotoContent>` | `onlyPhotoContentMessages` |
|
||||||
|
| Poll | `ContentMessage<PollContent>` | `onlyPollContentMessages` |
|
||||||
|
| Sticker | `ContentMessage<StickerContent>` | `onlyStickerContentMessages` |
|
||||||
|
| Text | `ContentMessage<TextContent>` | `onlyTextContentMessages` |
|
||||||
|
| Venue | `ContentMessage<VenueContent>` | `onlyVenueContentMessages` |
|
||||||
|
| Video | `ContentMessage<VideoContent>` | `onlyVideoContentMessages` |
|
||||||
|
| VideoNote | `ContentMessage<VideoNoteContent>` | `onlyVideoNoteContentMessages` |
|
||||||
|
| Voice | `ContentMessage<VoiceContent>` | `onlyVoiceContentMessages` |
|
||||||
|
|
||||||
|
For example, if you wish to get only photo messages from private chats of groups, you should call next code:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
filter.messageFlow.asContentMessagesFlow().onlyPhotoContentMessages().onEach {
|
||||||
println(it.content)
|
println(it.content)
|
||||||
println(it.fullEntitiesList())
|
|
||||||
}.launchIn(
|
}.launchIn(
|
||||||
CoroutineScope(Dispatchers.Default)
|
CoroutineScope(Dispatchers.Default)
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
As a result, each received message which will be just text message will be printed out with full list of its internal entities
|
##### Chat actions
|
||||||
|
|
||||||
## Shortcuts
|
Chat actions can be divided for three types of events source:
|
||||||
|
|
||||||
|
| Type | Flow extension |
|
||||||
|
|:---- |:-------------- |
|
||||||
|
| Channel events | `onlyChannelEvents` |
|
||||||
|
| Group events | `onlyGroupEvents` |
|
||||||
|
| Supergroup events | `onlySupergroupEvents` |
|
||||||
|
|
||||||
|
According to this table, if you want to add filtering by supergroup events, you will use code like this:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
filter.messageFlow.asChatEventsFlow().onlySupergroupEvents().onEach {
|
||||||
|
println(it.chatEvent)
|
||||||
|
}.launchIn(
|
||||||
|
CoroutineScope(Dispatchers.Default)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Shortcuts
|
||||||
|
|
||||||
With shortcuts you are able to use simple factories for several things.
|
With shortcuts you are able to use simple factories for several things.
|
||||||
|
|
||||||
### ScheduledCloseInfo
|
#### ScheduledCloseInfo
|
||||||
|
|
||||||
In case if you are creating some poll, you able to use next shortcuts.
|
In case if you are creating some poll, you able to use next shortcuts.
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ kotlin {
|
|||||||
if ((project.hasProperty('RELEASE_MODE') && project.property('RELEASE_MODE') == "true") || System.getenv('RELEASE_MODE') == "true") {
|
if ((project.hasProperty('RELEASE_MODE') && project.property('RELEASE_MODE') == "true") || System.getenv('RELEASE_MODE') == "true") {
|
||||||
api "${project.group}:TelegramBotAPI:$library_version"
|
api "${project.group}:TelegramBotAPI:$library_version"
|
||||||
} else {
|
} else {
|
||||||
implementation project(":TelegramBotAPI")
|
api project(":TelegramBotAPI")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,37 +20,33 @@ publishing {
|
|||||||
publications.all {
|
publications.all {
|
||||||
artifact javadocsJar
|
artifact javadocsJar
|
||||||
|
|
||||||
pom.withXml {
|
pom {
|
||||||
asNode().children().last() + {
|
description = "Util extensions for more useful work with updates and other things"
|
||||||
resolveStrategy = Closure.DELEGATE_FIRST
|
name = "Telegram Bot API Utility Extensions"
|
||||||
|
url = "https://insanusmokrassar.github.io/TelegramBotAPI/TelegramBotAPI-extensions-utils"
|
||||||
|
|
||||||
description "Util extensions for more useful work with updates and other things"
|
scm {
|
||||||
name "Telegram Bot API Utility Extensions"
|
developerConnection = "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
||||||
url "https://insanusmokrassar.github.io/TelegramBotAPI"
|
url = "https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
||||||
|
}
|
||||||
|
|
||||||
scm {
|
developers {
|
||||||
developerConnection "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
|
||||||
url "https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
developer {
|
||||||
}
|
id = "InsanusMokrassar"
|
||||||
|
name = "Ovsiannikov Aleksei"
|
||||||
|
email = "ovsyannikov.alexey95@gmail.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
developers {
|
licenses {
|
||||||
|
|
||||||
developer {
|
license {
|
||||||
id "InsanusMokrassar"
|
name = "Apache Software License 2.0"
|
||||||
name "Ovsiannikov Aleksei"
|
url = "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
|
||||||
email "ovsyannikov.alexey95@gmail.com"
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
licenses {
|
|
||||||
|
|
||||||
license {
|
|
||||||
name "Apache Software License 2.0"
|
|
||||||
url "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"bintrayConfig":{"repo":"StandardRepository","packageName":"${project.name}","packageVcs":"https://github.com/InsanusMokrassar/TelegramBotAPI"},"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"}],"mavenConfig":{"name":"Telegram Bot API Utility Extensions","description":"Util extensions for more useful work with updates and other things","url":"https://insanusmokrassar.github.io/TelegramBotAPI","vcsUrl":"https://github.com/insanusmokrassar/TelegramBotAPI.git","developers":[{"id":"InsanusMokrassar","name":"Ovsiannikov Aleksei","eMail":"ovsyannikov.alexey95@gmail.com"}]},"type":"Multiplatform"}
|
{"bintrayConfig":{"repo":"StandardRepository","packageName":"${project.name}","packageVcs":"https://github.com/InsanusMokrassar/TelegramBotAPI"},"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"}],"mavenConfig":{"name":"Telegram Bot API Utility Extensions","description":"Util extensions for more useful work with updates and other things","url":"https://insanusmokrassar.github.io/TelegramBotAPI/TelegramBotAPI-extensions-utils","vcsUrl":"https://github.com/insanusmokrassar/TelegramBotAPI.git","developers":[{"id":"InsanusMokrassar","name":"Ovsiannikov Aleksei","eMail":"ovsyannikov.alexey95@gmail.com"}]},"type":"Multiplatform"}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.CommonMessage
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MessageContent
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.PossiblySentViaBotCommonMessage
|
||||||
|
import kotlinx.coroutines.flow.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple factory to convert [ContentMessage] to a [CommonMessage]
|
||||||
|
*/
|
||||||
|
fun <C: MessageContent, T : ContentMessage<C>> Flow<T>.onlyCommonMessages() = filterIsInstance<CommonMessage<C>>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter the messages and checking that incoming [CommonMessage] is [PossiblySentViaBotCommonMessage] and its
|
||||||
|
* [PossiblySentViaBotCommonMessage.senderBot] is not null
|
||||||
|
*/
|
||||||
|
fun <T : MessageContent> Flow<CommonMessage<T>>.onlySentViaBot() = mapNotNull {
|
||||||
|
(it as? PossiblySentViaBotCommonMessage) ?.let { possiblySentViaBot ->
|
||||||
|
if (possiblySentViaBot.senderBot != null) {
|
||||||
|
possiblySentViaBot
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter the messages and checking that incoming [CommonMessage] not is [PossiblySentViaBotCommonMessage] or its
|
||||||
|
* [PossiblySentViaBotCommonMessage.senderBot] is null
|
||||||
|
*/
|
||||||
|
fun <T : MessageContent> Flow<CommonMessage<T>>.withoutSentViaBot() = filter {
|
||||||
|
it !is PossiblySentViaBotCommonMessage || it.senderBot == null
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils
|
||||||
|
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
|
@Suppress("EXPERIMENTAL_API_USAGE")
|
||||||
|
internal val nonstrictJsonFormat = Json {
|
||||||
|
isLenient = true
|
||||||
|
ignoreUnknownKeys = true
|
||||||
|
serializeSpecialFloatingPointValues = true
|
||||||
|
useArrayPolymorphism = true
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.*
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shortcut for [handleSafely]. It was created for more comfortable way of handling different things
|
||||||
|
*/
|
||||||
|
@PreviewFeature
|
||||||
|
suspend inline fun <T> safely(
|
||||||
|
noinline onException: ExceptionHandler<T> = { throw it },
|
||||||
|
noinline block: suspend CoroutineScope.() -> T
|
||||||
|
): T = handleSafely(
|
||||||
|
onException,
|
||||||
|
block
|
||||||
|
)
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.chat_events
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ChatEventMessage
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.mapNotNull
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
|
||||||
|
fun <T : ChatEventMessage> Flow<ChatEventMessage>.divideBySource(contentType: KClass<T>) = mapNotNull {
|
||||||
|
if (contentType.isInstance(it)) {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
it as T
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Flow<ChatEventMessage>.onlyChannelEvents() = divideBySource(ChannelEventMessage::class)
|
||||||
|
fun Flow<ChatEventMessage>.onlyGroupEvents() = divideBySource(GroupEventMessage::class)
|
||||||
|
fun Flow<ChatEventMessage>.onlySupergroupEvents() = divideBySource(SupergroupEventMessage::class)
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.extensions.venue
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.venue.Venue
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
val Venue.foursquare: Foursquare?
|
||||||
|
get() = foursquareId ?.let {
|
||||||
|
Foursquare(it, foursquareType)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Venue(
|
||||||
|
location: Location,
|
||||||
|
title: String,
|
||||||
|
address: String,
|
||||||
|
foursquare: Foursquare
|
||||||
|
) = Venue(location, title, address, foursquare.id, foursquare.type)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Foursquare(
|
||||||
|
@SerialName(foursquareIdField)
|
||||||
|
val id: FoursquareId,
|
||||||
|
@SerialName(foursquareTypeField)
|
||||||
|
val type: FoursquareType? = null
|
||||||
|
)
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.formatting
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.PrivateChat
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.UsernameChat
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.extended.ExtendedChat
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.link
|
||||||
|
|
||||||
|
private const val internalLinkBeginning = "https://t.me"
|
||||||
|
|
||||||
|
fun makeLinkToMessage(
|
||||||
|
username: String,
|
||||||
|
messageId: MessageIdentifier
|
||||||
|
): String = "$internalLinkBeginning/$username/$messageId"
|
||||||
|
fun makeLinkToMessage(
|
||||||
|
username: Username,
|
||||||
|
messageId: MessageIdentifier
|
||||||
|
): String = makeLinkToMessage(username.username, messageId)
|
||||||
|
fun makeLinkToMessage(
|
||||||
|
chat: UsernameChat,
|
||||||
|
messageId: MessageIdentifier
|
||||||
|
): String? = chat.username ?.let { makeLinkToMessage(it, messageId) }
|
||||||
|
|
||||||
|
private val linkIdRedundantPartRegex = Regex("^-100")
|
||||||
|
private val usernameBeginSymbolRegex = Regex("^@")
|
||||||
|
|
||||||
|
fun makeLinkToMessage(
|
||||||
|
chat: ExtendedChat,
|
||||||
|
messageId: MessageIdentifier
|
||||||
|
): String? {
|
||||||
|
return when {
|
||||||
|
chat is UsernameChat && chat.username != null -> {
|
||||||
|
"$internalLinkBeginning/${chat.username ?.username ?.replace(
|
||||||
|
usernameBeginSymbolRegex, "")}/$messageId"
|
||||||
|
}
|
||||||
|
chat !is PrivateChat -> chat.id.chatId.toString().replace(
|
||||||
|
linkIdRedundantPartRegex,
|
||||||
|
""
|
||||||
|
).let { bareId ->
|
||||||
|
"$internalLinkBeginning/c/$bareId/$messageId"
|
||||||
|
}
|
||||||
|
else -> return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private const val stickerSetAddingLinkPrefix = "$internalLinkBeginning/addstickers"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a link for adding of sticker set with name [stickerSetName]. Was added thanks to user Djaler and based on
|
||||||
|
* https://github.com/Djaler/evil-bot/blob/master/src/main/kotlin/com/github/djaler/evilbot/utils/StickerUtils.kt#L6-L8
|
||||||
|
*
|
||||||
|
* @see [makeLinkToAddStickerSetInMarkdownV2]
|
||||||
|
* @see [makeLinkToAddStickerSetInMarkdown]
|
||||||
|
* @see [makeLinkToAddStickerSetInHtml]
|
||||||
|
*/
|
||||||
|
fun makeLinkToAddStickerSet(
|
||||||
|
stickerSetName: StickerSetName,
|
||||||
|
parseMode: ParseMode
|
||||||
|
) = (stickerSetName to "$stickerSetAddingLinkPrefix/$stickerSetName").link(
|
||||||
|
parseMode
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Link for adding of sticker set with name [stickerSetName] with formatting for [MarkdownV2]
|
||||||
|
*/
|
||||||
|
fun makeLinkToAddStickerSetInMarkdownV2(stickerSetName: StickerSetName) =
|
||||||
|
makeLinkToAddStickerSet(
|
||||||
|
stickerSetName,
|
||||||
|
MarkdownV2
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* @return Link for adding of sticker set with name [stickerSetName] with formatting for [Markdown]
|
||||||
|
*/
|
||||||
|
fun makeLinkToAddStickerSetInMarkdown(stickerSetName: StickerSetName) =
|
||||||
|
makeLinkToAddStickerSet(
|
||||||
|
stickerSetName,
|
||||||
|
Markdown
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* @return Link for adding of sticker set with name [stickerSetName] with formatting for [HTML]
|
||||||
|
*/
|
||||||
|
fun makeLinkToAddStickerSetInHtml(stickerSetName: StickerSetName) =
|
||||||
|
makeLinkToAddStickerSet(
|
||||||
|
stickerSetName,
|
||||||
|
HTML
|
||||||
|
)
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.formatting
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.CommonAbstracts.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.TextContent
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.fullEntitiesList
|
||||||
|
|
||||||
|
fun createFormattedText(
|
||||||
|
entities: FullTextSourcesList,
|
||||||
|
partLength: Int = textLength.last,
|
||||||
|
mode: ParseMode = MarkdownParseMode
|
||||||
|
): List<String> {
|
||||||
|
val texts = mutableListOf<String>()
|
||||||
|
val textBuilder = StringBuilder(partLength)
|
||||||
|
for (entity in entities) {
|
||||||
|
val string = when (mode) {
|
||||||
|
is MarkdownParseMode -> entity.asMarkdownSource
|
||||||
|
is MarkdownV2ParseMode -> entity.asMarkdownV2Source
|
||||||
|
is HTMLParseMode -> entity.asHtmlSource
|
||||||
|
}
|
||||||
|
if (textBuilder.length + string.length > partLength) {
|
||||||
|
if (textBuilder.isNotEmpty()) {
|
||||||
|
texts.add(textBuilder.toString())
|
||||||
|
textBuilder.clear()
|
||||||
|
}
|
||||||
|
val chunked = string.chunked(partLength)
|
||||||
|
val last = chunked.last()
|
||||||
|
textBuilder.append(last)
|
||||||
|
val listToAdd = if (chunked.size > 1) {
|
||||||
|
chunked.subList(0, chunked.size - 1)
|
||||||
|
} else {
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
listToAdd.forEach {
|
||||||
|
texts.add(it)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
textBuilder.append(string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (textBuilder.isNotEmpty()) {
|
||||||
|
texts.add(textBuilder.toString())
|
||||||
|
textBuilder.clear()
|
||||||
|
}
|
||||||
|
return texts
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun createMarkdownText(
|
||||||
|
entities: FullTextSourcesList,
|
||||||
|
partLength: Int = textLength.last
|
||||||
|
): List<String> = createFormattedText(entities, partLength, MarkdownParseMode)
|
||||||
|
|
||||||
|
fun FullTextSourcesList.toMarkdownCaptions(): List<String> = createMarkdownText(
|
||||||
|
this,
|
||||||
|
captionLength.last
|
||||||
|
)
|
||||||
|
fun CaptionedInput.toMarkdownCaptions(): List<String> = fullEntitiesList().toMarkdownCaptions()
|
||||||
|
|
||||||
|
fun FullTextSourcesList.toMarkdownTexts(): List<String> = createMarkdownText(
|
||||||
|
this,
|
||||||
|
textLength.last
|
||||||
|
)
|
||||||
|
fun TextContent.toMarkdownTexts(): List<String> = fullEntitiesList().toMarkdownTexts()
|
||||||
|
|
||||||
|
fun FullTextSourcesList.toMarkdownExplanations(): List<String> = createMarkdownText(
|
||||||
|
this,
|
||||||
|
explanationLimit.last
|
||||||
|
)
|
||||||
|
fun ExplainedInput.toMarkdownExplanations(): List<String> = fullEntitiesList().toMarkdownTexts()
|
||||||
|
|
||||||
|
|
||||||
|
fun createMarkdownV2Text(
|
||||||
|
entities: FullTextSourcesList,
|
||||||
|
partLength: Int = textLength.last
|
||||||
|
): List<String> = createFormattedText(entities, partLength, MarkdownV2ParseMode)
|
||||||
|
|
||||||
|
fun FullTextSourcesList.toMarkdownV2Captions(): List<String> = createMarkdownV2Text(
|
||||||
|
this,
|
||||||
|
captionLength.last
|
||||||
|
)
|
||||||
|
fun CaptionedInput.toMarkdownV2Captions(): List<String> = fullEntitiesList().toMarkdownV2Captions()
|
||||||
|
|
||||||
|
fun FullTextSourcesList.toMarkdownV2Texts(): List<String> = createMarkdownV2Text(
|
||||||
|
this,
|
||||||
|
textLength.last
|
||||||
|
)
|
||||||
|
fun TextContent.toMarkdownV2Texts(): List<String> = fullEntitiesList().toMarkdownV2Texts()
|
||||||
|
|
||||||
|
fun FullTextSourcesList.toMarkdownV2Explanations(): List<String> = createMarkdownV2Text(
|
||||||
|
this,
|
||||||
|
explanationLimit.last
|
||||||
|
)
|
||||||
|
fun ExplainedInput.toMarkdownV2Explanations(): List<String> = fullEntitiesList().toMarkdownV2Texts()
|
||||||
|
|
||||||
|
|
||||||
|
fun createHtmlText(
|
||||||
|
entities: FullTextSourcesList,
|
||||||
|
partLength: Int = textLength.last
|
||||||
|
): List<String> = createFormattedText(entities, partLength, HTMLParseMode)
|
||||||
|
|
||||||
|
fun FullTextSourcesList.toHtmlCaptions(): List<String> = createHtmlText(
|
||||||
|
this,
|
||||||
|
captionLength.last
|
||||||
|
)
|
||||||
|
fun CaptionedInput.toHtmlCaptions(): List<String> = fullEntitiesList().toHtmlCaptions()
|
||||||
|
|
||||||
|
fun FullTextSourcesList.toHtmlTexts(): List<String> = createHtmlText(
|
||||||
|
this,
|
||||||
|
textLength.last
|
||||||
|
)
|
||||||
|
fun TextContent.toHtmlTexts(): List<String> = fullEntitiesList().toHtmlTexts()
|
||||||
|
|
||||||
|
fun FullTextSourcesList.toHtmlExplanations(): List<String> = createHtmlText(
|
||||||
|
this,
|
||||||
|
explanationLimit.last
|
||||||
|
)
|
||||||
|
fun ExplainedInput.toHtmlExplanations(): List<String> = fullEntitiesList().toHtmlTexts()
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,243 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.formatting
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.extensions.*
|
||||||
|
|
||||||
|
const val markdownBoldControl = "*"
|
||||||
|
const val markdownItalicControl = "_"
|
||||||
|
const val markdownCodeControl = "`"
|
||||||
|
const val markdownPreControl = "```"
|
||||||
|
|
||||||
|
const val markdownV2ItalicUnderlineDelimiter = "\u0013"
|
||||||
|
const val markdownV2StrikethroughControl = "~"
|
||||||
|
const val markdownV2UnderlineControl = "__"
|
||||||
|
const val markdownV2UnderlineEndControl = "$markdownV2UnderlineControl$markdownV2ItalicUnderlineDelimiter"
|
||||||
|
const val markdownV2ItalicEndControl = "$markdownItalicControl$markdownV2ItalicUnderlineDelimiter"
|
||||||
|
|
||||||
|
const val htmlBoldControl = "b"
|
||||||
|
const val htmlItalicControl = "i"
|
||||||
|
const val htmlCodeControl = "code"
|
||||||
|
const val htmlPreControl = "pre"
|
||||||
|
const val htmlUnderlineControl = "u"
|
||||||
|
const val htmlStrikethroughControl = "s"
|
||||||
|
|
||||||
|
private fun String.markdownDefault(
|
||||||
|
openControlSymbol: String,
|
||||||
|
closeControlSymbol: String = openControlSymbol
|
||||||
|
) = "$openControlSymbol${toMarkdown()}$closeControlSymbol"
|
||||||
|
private fun String.markdownV2Default(
|
||||||
|
openControlSymbol: String,
|
||||||
|
closeControlSymbol: String = openControlSymbol,
|
||||||
|
escapeFun: String.() -> String = String::escapeMarkdownV2Common
|
||||||
|
) = "$openControlSymbol${escapeFun()}$closeControlSymbol"
|
||||||
|
private fun String.htmlDefault(
|
||||||
|
openControlSymbol: String,
|
||||||
|
closeControlSymbol: String = openControlSymbol
|
||||||
|
) = "<$openControlSymbol>${toHtml()}</$closeControlSymbol>"
|
||||||
|
|
||||||
|
fun String.linkMarkdown(link: String): String = "[${toMarkdown()}](${link.toMarkdown()})"
|
||||||
|
fun String.linkMarkdownV2(link: String): String = "[${escapeMarkdownV2Common()}](${link.escapeMarkdownV2Link()})"
|
||||||
|
fun String.linkHTML(link: String): String = "<a href=\"$link\">${toHtml()}</a>"
|
||||||
|
|
||||||
|
|
||||||
|
fun String.boldMarkdown(): String = markdownDefault(markdownBoldControl)
|
||||||
|
fun String.boldMarkdownV2(): String = markdownV2Default(markdownBoldControl)
|
||||||
|
fun String.boldHTML(): String = htmlDefault(htmlBoldControl)
|
||||||
|
|
||||||
|
|
||||||
|
fun String.italicMarkdown(): String = markdownDefault(markdownItalicControl)
|
||||||
|
fun String.italicMarkdownV2(): String = markdownV2Default(markdownItalicControl, markdownV2ItalicEndControl)
|
||||||
|
fun String.italicHTML(): String = htmlDefault(htmlItalicControl)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crutch for support of strikethrough in default markdown. Simply add modifier, but it will not look like correct
|
||||||
|
*/
|
||||||
|
fun String.strikethroughMarkdown(): String = map { it + "\u0336" }.joinToString("")
|
||||||
|
fun String.strikethroughMarkdownV2(): String = markdownV2Default(markdownV2StrikethroughControl)
|
||||||
|
fun String.strikethroughHTML(): String = htmlDefault(htmlStrikethroughControl)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crutch for support of underline in default markdown. Simply add modifier, but it will not look like correct
|
||||||
|
*/
|
||||||
|
fun String.underlineMarkdown(): String = map { it + "\u0347" }.joinToString("")
|
||||||
|
fun String.underlineMarkdownV2(): String = markdownV2Default(markdownV2UnderlineControl, markdownV2UnderlineEndControl)
|
||||||
|
fun String.underlineHTML(): String = htmlDefault(htmlUnderlineControl)
|
||||||
|
|
||||||
|
|
||||||
|
fun String.codeMarkdown(): String = markdownDefault(markdownCodeControl)
|
||||||
|
fun String.codeMarkdownV2(): String = markdownV2Default(markdownCodeControl, escapeFun = String::escapeMarkdownV2PreAndCode)
|
||||||
|
fun String.codeHTML(): String = htmlDefault(htmlCodeControl)
|
||||||
|
|
||||||
|
|
||||||
|
fun String.preMarkdown(language: String? = null): String = markdownDefault(
|
||||||
|
"$markdownPreControl${language ?: ""}\n",
|
||||||
|
"\n$markdownPreControl"
|
||||||
|
)
|
||||||
|
fun String.preMarkdownV2(language: String? = null): String = markdownV2Default(
|
||||||
|
"$markdownPreControl${language ?: ""}\n",
|
||||||
|
"\n$markdownPreControl",
|
||||||
|
String::escapeMarkdownV2PreAndCode
|
||||||
|
)
|
||||||
|
fun String.preHTML(language: String? = null): String = htmlDefault(
|
||||||
|
language ?.let {
|
||||||
|
"$htmlPreControl><$htmlCodeControl class=\"language-$language\""
|
||||||
|
} ?: htmlPreControl,
|
||||||
|
language ?.let {
|
||||||
|
"$htmlCodeControl></$htmlPreControl"
|
||||||
|
} ?: htmlPreControl
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
fun String.emailMarkdown(): String = linkMarkdown("mailto://$${toMarkdown()}")
|
||||||
|
fun String.emailMarkdownV2(): String = linkMarkdownV2("mailto://$${toMarkdown()}")
|
||||||
|
fun String.emailHTML(): String = linkHTML("mailto://$${toHtml()}")
|
||||||
|
|
||||||
|
|
||||||
|
private inline fun String.mention(adapt: String.() -> String): String = if (startsWith("@")) {
|
||||||
|
adapt()
|
||||||
|
} else {
|
||||||
|
"@${adapt()}"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private inline fun String.hashTag(adapt: String.() -> String): String = if (startsWith("#")) {
|
||||||
|
adapt()
|
||||||
|
} else {
|
||||||
|
"#${adapt()}"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun String.textMentionMarkdown(userId: UserId): String = linkMarkdown(userId.link)
|
||||||
|
fun String.textMentionMarkdownV2(userId: UserId): String = linkMarkdownV2(userId.link)
|
||||||
|
fun String.textMentionHTML(userId: UserId): String = linkHTML(userId.link)
|
||||||
|
|
||||||
|
|
||||||
|
fun String.mentionMarkdown(): String = mention(String::toMarkdown)
|
||||||
|
fun String.mentionMarkdownV2(): String = mention(String::escapeMarkdownV2Common)
|
||||||
|
fun String.mentionHTML(): String = mention(String::toHtml)
|
||||||
|
|
||||||
|
|
||||||
|
fun String.hashTagMarkdown(): String = hashTag(String::toMarkdown)
|
||||||
|
fun String.hashTagMarkdownV2(): String = hashTag(String::escapeMarkdownV2Common).escapeMarkdownV2Common()
|
||||||
|
fun String.hashTagHTML(): String = hashTag(String::toHtml)
|
||||||
|
|
||||||
|
|
||||||
|
fun String.phoneMarkdown(): String = toMarkdown()
|
||||||
|
fun String.phoneMarkdownV2(): String = escapeMarkdownV2Common()
|
||||||
|
fun String.phoneHTML(): String = toHtml()
|
||||||
|
|
||||||
|
|
||||||
|
fun String.command(adapt: String.() -> String): String = if (startsWith("/")) {
|
||||||
|
adapt()
|
||||||
|
} else {
|
||||||
|
"/${adapt()}"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun String.commandMarkdown(): String = command(String::toMarkdown)
|
||||||
|
fun String.commandMarkdownV2(): String = command(String::escapeMarkdownV2Common)
|
||||||
|
fun String.commandHTML(): String = command(String::toHtml)
|
||||||
|
|
||||||
|
|
||||||
|
fun String.regularMarkdown(): String = toMarkdown()
|
||||||
|
fun String.regularMarkdownV2(): String = escapeMarkdownV2Common()
|
||||||
|
fun String.regularHtml(): String = toHtml()
|
||||||
|
|
||||||
|
|
||||||
|
fun String.cashTagMarkdown(): String = toMarkdown()
|
||||||
|
fun String.cashTagMarkdownV2(): String = escapeMarkdownV2Common()
|
||||||
|
fun String.cashTagHtml(): String = toHtml()
|
||||||
|
|
||||||
|
|
||||||
|
infix fun String.bold(parseMode: ParseMode): String = when (parseMode) {
|
||||||
|
is HTML -> boldHTML()
|
||||||
|
is Markdown -> boldMarkdown()
|
||||||
|
is MarkdownV2 -> boldMarkdownV2()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
infix fun String.italic(parseMode: ParseMode): String = when (parseMode) {
|
||||||
|
is HTML -> italicHTML()
|
||||||
|
is Markdown -> italicMarkdown()
|
||||||
|
is MarkdownV2 -> italicMarkdownV2()
|
||||||
|
}
|
||||||
|
|
||||||
|
infix fun String.hashTag(parseMode: ParseMode): String = when (parseMode) {
|
||||||
|
is HTML -> hashTagHTML()
|
||||||
|
is Markdown -> hashTagMarkdown()
|
||||||
|
is MarkdownV2 -> hashTagMarkdownV2()
|
||||||
|
}
|
||||||
|
|
||||||
|
infix fun String.code(parseMode: ParseMode): String = when (parseMode) {
|
||||||
|
is HTML -> codeHTML()
|
||||||
|
is Markdown -> codeMarkdown()
|
||||||
|
is MarkdownV2 -> codeMarkdownV2()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun String.pre(parseMode: ParseMode, language: String? = null): String = when (parseMode) {
|
||||||
|
is HTML -> preHTML(language)
|
||||||
|
is Markdown -> preMarkdown(language)
|
||||||
|
is MarkdownV2 -> preMarkdownV2(language)
|
||||||
|
}
|
||||||
|
infix fun String.pre(parseMode: ParseMode): String = pre(parseMode, null)
|
||||||
|
|
||||||
|
infix fun String.email(parseMode: ParseMode): String = when (parseMode) {
|
||||||
|
is HTML -> emailHTML()
|
||||||
|
is Markdown -> emailMarkdown()
|
||||||
|
is MarkdownV2 -> emailMarkdownV2()
|
||||||
|
}
|
||||||
|
|
||||||
|
infix fun Pair<String, String>.link(parseMode: ParseMode): String = when (parseMode) {
|
||||||
|
is HTML -> first.linkHTML(second)
|
||||||
|
is Markdown -> first.linkMarkdown(second)
|
||||||
|
is MarkdownV2 -> first.linkMarkdownV2(second)
|
||||||
|
}
|
||||||
|
|
||||||
|
infix fun String.mention(parseMode: ParseMode): String = when (parseMode) {
|
||||||
|
is HTML -> mentionHTML()
|
||||||
|
is Markdown -> mentionMarkdown()
|
||||||
|
is MarkdownV2 -> mentionMarkdownV2()
|
||||||
|
}
|
||||||
|
|
||||||
|
infix fun Pair<String, ChatId>.mention(parseMode: ParseMode): String = when (parseMode) {
|
||||||
|
is HTML -> first.textMentionHTML(second)
|
||||||
|
is Markdown -> first.textMentionMarkdown(second)
|
||||||
|
is MarkdownV2 -> first.textMentionMarkdownV2(second)
|
||||||
|
}
|
||||||
|
|
||||||
|
infix fun String.phone(parseMode: ParseMode): String = when (parseMode) {
|
||||||
|
is HTML -> phoneHTML()
|
||||||
|
is Markdown -> phoneMarkdown()
|
||||||
|
is MarkdownV2 -> phoneMarkdownV2()
|
||||||
|
}
|
||||||
|
|
||||||
|
infix fun String.command(parseMode: ParseMode): String = when (parseMode) {
|
||||||
|
is HTML -> commandHTML()
|
||||||
|
is Markdown -> commandMarkdown()
|
||||||
|
is MarkdownV2 -> commandMarkdownV2()
|
||||||
|
}
|
||||||
|
|
||||||
|
infix fun String.underline(parseMode: ParseMode): String = when (parseMode) {
|
||||||
|
is HTML -> underlineHTML()
|
||||||
|
is Markdown -> underlineMarkdown()
|
||||||
|
is MarkdownV2 -> underlineMarkdownV2()
|
||||||
|
}
|
||||||
|
|
||||||
|
infix fun String.strikethrough(parseMode: ParseMode): String = when (parseMode) {
|
||||||
|
is HTML -> strikethroughHTML()
|
||||||
|
is Markdown -> strikethroughMarkdown()
|
||||||
|
is MarkdownV2 -> strikethroughMarkdownV2()
|
||||||
|
}
|
||||||
|
|
||||||
|
infix fun String.regular(parseMode: ParseMode): String = when (parseMode) {
|
||||||
|
is HTML -> regularHtml()
|
||||||
|
is Markdown -> regularMarkdown()
|
||||||
|
is MarkdownV2 -> regularMarkdownV2()
|
||||||
|
}
|
||||||
|
|
||||||
|
infix fun String.cashtag(parseMode: ParseMode): String = when (parseMode) {
|
||||||
|
is HTML -> cashTagHtml()
|
||||||
|
is Markdown -> cashTagMarkdown()
|
||||||
|
is MarkdownV2 -> cashTagMarkdownV2()
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.shortcuts
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.requests.send.media.SendMediaGroup
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.Chat
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.ForwardInfo
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.MediaGroupMessage
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Message
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates.SentMediaGroupUpdate
|
||||||
|
|
||||||
|
val List<MediaGroupMessage>.forwardInfo: ForwardInfo?
|
||||||
|
get() = firstOrNull() ?.forwardInfo
|
||||||
|
val List<MediaGroupMessage>.replyTo: Message?
|
||||||
|
get() = firstOrNull() ?.replyTo
|
||||||
|
val List<MediaGroupMessage>.chat: Chat?
|
||||||
|
get() = firstOrNull() ?.chat
|
||||||
|
val List<MediaGroupMessage>.mediaGroupId: MediaGroupIdentifier?
|
||||||
|
get() = firstOrNull() ?.mediaGroupId
|
||||||
|
|
||||||
|
val SentMediaGroupUpdate.forwardInfo: ForwardInfo?
|
||||||
|
get() = data.first().forwardInfo
|
||||||
|
val SentMediaGroupUpdate.replyTo: Message?
|
||||||
|
get() = data.first().replyTo
|
||||||
|
val SentMediaGroupUpdate.chat: Chat
|
||||||
|
get() = data.chat!!
|
||||||
|
val SentMediaGroupUpdate.mediaGroupId: MediaGroupIdentifier
|
||||||
|
get() = data.mediaGroupId!!
|
||||||
|
|
||||||
|
fun List<MediaGroupMessage>.createResend(
|
||||||
|
chatId: ChatId,
|
||||||
|
disableNotification: Boolean = false,
|
||||||
|
replyTo: MessageIdentifier? = null
|
||||||
|
) = SendMediaGroup(
|
||||||
|
chatId,
|
||||||
|
map { it.content.toMediaGroupMemberInputMedia() },
|
||||||
|
disableNotification,
|
||||||
|
replyTo
|
||||||
|
)
|
||||||
|
|
||||||
|
fun List<MediaGroupMessage>.createResend(
|
||||||
|
chat: Chat,
|
||||||
|
disableNotification: Boolean = false,
|
||||||
|
replyTo: MessageIdentifier? = null
|
||||||
|
) = createResend(
|
||||||
|
chat.id,
|
||||||
|
disableNotification,
|
||||||
|
replyTo
|
||||||
|
)
|
||||||
|
|
||||||
|
fun SentMediaGroupUpdate.createResend(
|
||||||
|
disableNotification: Boolean = false,
|
||||||
|
replyTo: MessageIdentifier? = null
|
||||||
|
) = data.createResend(
|
||||||
|
chat,
|
||||||
|
disableNotification,
|
||||||
|
replyTo
|
||||||
|
)
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.shortcuts
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.bot.RequestsExecutor
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.handleSafely
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
|
||||||
|
fun <T: Any> RequestsExecutor.executeAsync(
|
||||||
|
request: Request<T>,
|
||||||
|
scope: CoroutineScope
|
||||||
|
): Deferred<T> = scope.async {
|
||||||
|
handleSafely {
|
||||||
|
execute(request)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun <T: Any> RequestsExecutor.executeAsync(
|
||||||
|
request: Request<T>
|
||||||
|
): Deferred<T> = coroutineScope {
|
||||||
|
executeAsync(request, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun <T: Any> RequestsExecutor.executeUnsafe(
|
||||||
|
request: Request<T>,
|
||||||
|
retries: Int = 0,
|
||||||
|
retriesDelay: Long = 1000L,
|
||||||
|
onAllFailed: (suspend (exceptions: Array<Exception>) -> Unit)? = null
|
||||||
|
): T? {
|
||||||
|
var leftRetries = retries
|
||||||
|
val exceptions = onAllFailed ?.let { mutableListOf<Exception>() }
|
||||||
|
do {
|
||||||
|
return handleSafely(
|
||||||
|
{
|
||||||
|
leftRetries--
|
||||||
|
delay(retriesDelay)
|
||||||
|
exceptions ?.add(it)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
execute(request)
|
||||||
|
} ?: continue
|
||||||
|
} while(leftRetries >= 0)
|
||||||
|
onAllFailed ?.invoke(exceptions ?.toTypedArray() ?: emptyArray())
|
||||||
|
return null
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.types.buttons
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardButtons.InlineKeyboardButton
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.flatMatrix
|
||||||
|
|
||||||
|
fun InlineKeyboardMarkup(
|
||||||
|
vararg buttons: InlineKeyboardButton
|
||||||
|
): InlineKeyboardMarkup = InlineKeyboardMarkup(
|
||||||
|
flatMatrix { buttons.forEach { +it } }
|
||||||
|
)
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.types.buttons
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardButton
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.ReplyKeyboardMarkup
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.flatMatrix
|
||||||
|
|
||||||
|
fun ReplyKeyboardMarkup(
|
||||||
|
vararg buttons: KeyboardButton,
|
||||||
|
resizeKeyboard: Boolean? = null,
|
||||||
|
oneTimeKeyboard: Boolean? = null,
|
||||||
|
selective: Boolean? = null
|
||||||
|
): ReplyKeyboardMarkup = ReplyKeyboardMarkup(
|
||||||
|
flatMatrix { buttons.forEach { +it } },
|
||||||
|
resizeKeyboard,
|
||||||
|
oneTimeKeyboard,
|
||||||
|
selective
|
||||||
|
)
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.updates
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.*
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.filterIsInstance
|
||||||
|
|
||||||
|
fun Flow<Update>.onlyBaseMessageUpdates(): Flow<BaseMessageUpdate> = filterIsInstance()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts flow to [Flow] of [BaseSentMessageUpdate]
|
||||||
|
*/
|
||||||
|
fun Flow<BaseMessageUpdate>.onlySentMessageUpdates(): Flow<BaseSentMessageUpdate> = filterIsInstance()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts flow to [Flow] of [BaseSentMessageUpdate]
|
||||||
|
*/
|
||||||
|
fun Flow<BaseMessageUpdate>.onlyEditMessageUpdates(): Flow<BaseEditMessageUpdate> = filterIsInstance()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts flow to [Flow] of [MediaGroupUpdate]. Please, remember that it could be either [EditMediaGroupUpdate]
|
||||||
|
* or [SentMediaGroupUpdate]
|
||||||
|
*
|
||||||
|
* @see onlySentMediaGroupUpdates
|
||||||
|
* @see onlyEditMediaGroupUpdates
|
||||||
|
*/
|
||||||
|
fun Flow<BaseMessageUpdate>.onlyMediaGroupsUpdates(): Flow<MediaGroupUpdate> = filterIsInstance()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts flow to [Flow] of [SentMediaGroupUpdate]
|
||||||
|
*/
|
||||||
|
fun Flow<MediaGroupUpdate>.onlySentMediaGroupUpdates(): Flow<SentMediaGroupUpdate> = filterIsInstance()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts flow to [Flow] of [EditMediaGroupUpdate]
|
||||||
|
*/
|
||||||
|
fun Flow<MediaGroupUpdate>.onlyEditMediaGroupUpdates(): Flow<EditMediaGroupUpdate> = filterIsInstance()
|
||||||
@@ -5,12 +5,21 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.update.CallbackQueryUpda
|
|||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.mapNotNull
|
import kotlinx.coroutines.flow.mapNotNull
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return New [Flow] with [DataCallbackQuery] type, got from [CallbackQueryUpdate.data] field
|
||||||
|
*/
|
||||||
fun Flow<CallbackQueryUpdate>.asDataCallbackQueryFlow() = mapNotNull {
|
fun Flow<CallbackQueryUpdate>.asDataCallbackQueryFlow() = mapNotNull {
|
||||||
it.data as? DataCallbackQuery
|
it.data as? DataCallbackQuery
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @return New [Flow] with [GameShortNameCallbackQuery] type, got from [CallbackQueryUpdate.data] field
|
||||||
|
*/
|
||||||
fun Flow<CallbackQueryUpdate>.asGameShortNameCallbackQueryFlow() = mapNotNull {
|
fun Flow<CallbackQueryUpdate>.asGameShortNameCallbackQueryFlow() = mapNotNull {
|
||||||
it.data as? GameShortNameCallbackQuery
|
it.data as? GameShortNameCallbackQuery
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @return New [Flow] with [UnknownCallbackQueryType] type, got from [CallbackQueryUpdate.data] field
|
||||||
|
*/
|
||||||
fun Flow<CallbackQueryUpdate>.asUnknownCallbackQueryFlow() = mapNotNull {
|
fun Flow<CallbackQueryUpdate>.asUnknownCallbackQueryFlow() = mapNotNull {
|
||||||
it.data as? UnknownCallbackQueryType
|
it.data as? UnknownCallbackQueryType
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,12 +8,37 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.fullEnti
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.BaseSentMessageUpdate
|
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.BaseSentMessageUpdate
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert incoming [com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage.content] of
|
||||||
|
* messages with [fullEntitiesList] and check that incoming message contains ONLY ONE [TextSource] and that is
|
||||||
|
* [BotCommandTextSource]. Besides, it is checking that [BotCommandTextSource.command] [Regex.matches] with incoming
|
||||||
|
* [commandRegex]
|
||||||
|
*
|
||||||
|
* @return The same message in case if it contains only [BotCommandTextSource] with [Regex.matches]
|
||||||
|
* [BotCommandTextSource.command]
|
||||||
|
*
|
||||||
|
* @see fullEntitiesList
|
||||||
|
* @see asContentMessagesFlow
|
||||||
|
* @see onlyTextContentMessages
|
||||||
|
*/
|
||||||
fun <T : BaseSentMessageUpdate> Flow<T>.filterExactCommands(
|
fun <T : BaseSentMessageUpdate> Flow<T>.filterExactCommands(
|
||||||
commandRegex: Regex
|
commandRegex: Regex
|
||||||
) = asContentMessagesFlow().onlyTextContentMessages().filter { contentMessage ->
|
) = asContentMessagesFlow().onlyTextContentMessages().filter { contentMessage ->
|
||||||
(contentMessage.content.fullEntitiesList().singleOrNull() as? BotCommandTextSource) ?.let { commandRegex.matches(it.command) } == true
|
(contentMessage.content.fullEntitiesList().singleOrNull() as? BotCommandTextSource) ?.let { commandRegex.matches(it.command) } == true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert incoming [com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage.content] of
|
||||||
|
* messages with [fullEntitiesList] and check that incoming message contains [BotCommandTextSource]. Besides, it is
|
||||||
|
* checking that [BotCommandTextSource.command] [Regex.matches] with incoming [commandRegex]
|
||||||
|
*
|
||||||
|
* @return The same message in case if it contains somewhere in text [BotCommandTextSource] with [Regex.matches]
|
||||||
|
* [BotCommandTextSource.command]
|
||||||
|
*
|
||||||
|
* @see fullEntitiesList
|
||||||
|
* @see asContentMessagesFlow
|
||||||
|
* @see onlyTextContentMessages
|
||||||
|
*/
|
||||||
fun <T : BaseSentMessageUpdate> Flow<T>.filterCommandsInsideTextMessages(
|
fun <T : BaseSentMessageUpdate> Flow<T>.filterCommandsInsideTextMessages(
|
||||||
commandRegex: Regex
|
commandRegex: Regex
|
||||||
) = asContentMessagesFlow().onlyTextContentMessages().filter { contentMessage ->
|
) = asContentMessagesFlow().onlyTextContentMessages().filter { contentMessage ->
|
||||||
@@ -23,10 +48,18 @@ fun <T : BaseSentMessageUpdate> Flow<T>.filterCommandsInsideTextMessages(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Result [Flow] will emit all [TextSource]s to the collector ONLY IN CASE if first [TextSource] is
|
* Convert incoming [com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage.content] of
|
||||||
* [BotCommandTextSource] and its [BotCommandTextSource.command] is [Regex.matches] to incoming [commandRegex]. Internal
|
* messages with [fullEntitiesList] and check that incoming message contains first [TextSource] as
|
||||||
* behaviour contains next rules: all incoming text sources will be passed as is, [RegularTextSource] will be divided
|
* [BotCommandTextSource]. Besides, it is checking that [BotCommandTextSource.command] [Regex.matches] with incoming
|
||||||
* by " " for several [RegularTextSource] which will contains not empty args without spaces
|
* [commandRegex] and for other [TextSource] objects used next rules: all incoming text sources will be passed as is,
|
||||||
|
* [RegularTextSource] will be split by " " for several [RegularTextSource] which will contains not empty args without
|
||||||
|
* spaces.
|
||||||
|
*
|
||||||
|
* @return Converted list with first entity [BotCommandTextSource] and than all others according to rules in description
|
||||||
|
*
|
||||||
|
* @see fullEntitiesList
|
||||||
|
* @see asContentMessagesFlow
|
||||||
|
* @see onlyTextContentMessages
|
||||||
*/
|
*/
|
||||||
fun <T : BaseSentMessageUpdate> Flow<T>.filterCommandsWithArgs(
|
fun <T : BaseSentMessageUpdate> Flow<T>.filterCommandsWithArgs(
|
||||||
commandRegex: Regex
|
commandRegex: Regex
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.updates
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.FlowsUpdatesFilter
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non-suspendable function for easy-to-use creating of [FlowsUpdatesFilter] and applying the block to it
|
||||||
|
*
|
||||||
|
* @see flowsUpdatesFilter
|
||||||
|
*/
|
||||||
|
inline fun flowsUpdatesFilter(
|
||||||
|
internalChannelsSizes: Int = 100,
|
||||||
|
block: FlowsUpdatesFilter.() -> Unit
|
||||||
|
): FlowsUpdatesFilter {
|
||||||
|
val filter = FlowsUpdatesFilter(internalChannelsSizes)
|
||||||
|
filter.block()
|
||||||
|
return filter
|
||||||
|
}
|
||||||
@@ -5,14 +5,30 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.BaseSen
|
|||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.mapNotNull
|
import kotlinx.coroutines.flow.mapNotNull
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will map incoming [BaseSentMessageUpdate]s to [ContentMessage] from [BaseSentMessageUpdate.data]
|
||||||
|
*/
|
||||||
fun <T : BaseSentMessageUpdate> Flow<T>.asContentMessagesFlow() = mapNotNull {
|
fun <T : BaseSentMessageUpdate> Flow<T>.asContentMessagesFlow() = mapNotNull {
|
||||||
it.data as? ContentMessage<*>
|
it.data as? ContentMessage<*>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will map incoming [BaseSentMessageUpdate]s to [CommonMessage] from [BaseSentMessageUpdate.data]
|
||||||
|
*/
|
||||||
|
fun <T : BaseSentMessageUpdate> Flow<T>.asCommonMessagesFlow() = mapNotNull {
|
||||||
|
it.data as? CommonMessage<*>
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will map incoming [BaseSentMessageUpdate]s to [ChatEventMessage] from [BaseSentMessageUpdate.data]
|
||||||
|
*/
|
||||||
fun <T : BaseSentMessageUpdate> Flow<T>.asChatEventsFlow() = mapNotNull {
|
fun <T : BaseSentMessageUpdate> Flow<T>.asChatEventsFlow() = mapNotNull {
|
||||||
it.data as? ChatEventMessage
|
it.data as? ChatEventMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will map incoming [BaseSentMessageUpdate]s to [UnknownMessageType] from [BaseSentMessageUpdate.data]
|
||||||
|
*/
|
||||||
fun <T : BaseSentMessageUpdate> Flow<T>.asUnknownMessagesFlow() = mapNotNull {
|
fun <T : BaseSentMessageUpdate> Flow<T>.asUnknownMessagesFlow() = mapNotNull {
|
||||||
it.data as? UnknownMessageType
|
it.data as? UnknownMessageType
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.updates
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.nonstrictJsonFormat
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.UpdateDeserializationStrategy
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.JsonElement
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Deserialize [source] as [com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update]
|
||||||
|
*/
|
||||||
|
fun Json.toTelegramUpdate(source: String) = parse(UpdateDeserializationStrategy, source)
|
||||||
|
/**
|
||||||
|
* @return Deserialize [source] as [com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update]
|
||||||
|
*/
|
||||||
|
fun Json.toTelegramUpdate(source: JsonElement) = fromJson(UpdateDeserializationStrategy, source)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Deserialize [this] as [com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update]. In fact,
|
||||||
|
* it is must be JSON
|
||||||
|
*
|
||||||
|
* @see Json.toTelegramUpdate
|
||||||
|
*/
|
||||||
|
fun String.toTelegramUpdate() = nonstrictJsonFormat.toTelegramUpdate(this)
|
||||||
|
/**
|
||||||
|
* @return Deserialize [this] as [com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update]
|
||||||
|
*
|
||||||
|
* @see Json.toTelegramUpdate
|
||||||
|
*/
|
||||||
|
fun JsonElement.toTelegramUpdate() = nonstrictJsonFormat.toTelegramUpdate(this)
|
||||||
|
|
||||||
|
|
||||||
@@ -7,13 +7,41 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.BaseMes
|
|||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.filter
|
import kotlinx.coroutines.flow.filter
|
||||||
|
|
||||||
fun <T : BaseMessageUpdate> Flow<T>.filterBaseMessageUpdates(chatId: ChatId): Flow<T> = filter {
|
/**
|
||||||
it.data.chat.id == chatId
|
* [Flow.filter] incoming [BaseMessageUpdate]s by their [ChatId]
|
||||||
}
|
*/
|
||||||
fun <T : BaseMessageUpdate> Flow<T>.filterBaseMessageUpdates(chat: Chat): Flow<T> = filterBaseMessageUpdates(chat.id)
|
fun <T : BaseMessageUpdate> Flow<T>.filterBaseMessageUpdatesByChatId(chatId: ChatId): Flow<T> = filter { it.data.chat.id == chatId }
|
||||||
|
/**
|
||||||
|
* [Flow.filter] incoming [BaseMessageUpdate]s by their [ChatId] using [Chat.id] of [chat]
|
||||||
|
*/
|
||||||
|
fun <T : BaseMessageUpdate> Flow<T>.filterBaseMessageUpdatesByChat(chat: Chat): Flow<T> = filterBaseMessageUpdatesByChatId(chat.id)
|
||||||
|
/**
|
||||||
|
* [Flow.filter] incoming [BaseMessageUpdate]s by their [ChatId]
|
||||||
|
*/
|
||||||
|
@Deprecated("Renamed", ReplaceWith("filterBaseMessageUpdatesByChatId"))
|
||||||
|
fun <T : BaseMessageUpdate> Flow<T>.filterBaseMessageUpdates(chatId: ChatId): Flow<T> = filterBaseMessageUpdatesByChatId(chatId)
|
||||||
|
/**
|
||||||
|
* [Flow.filter] incoming [BaseMessageUpdate]s by their [ChatId] using [Chat.id] of [chat]
|
||||||
|
*/
|
||||||
|
@Deprecated("Renamed", ReplaceWith("filterBaseMessageUpdatesByChat"))
|
||||||
|
fun <T : BaseMessageUpdate> Flow<T>.filterBaseMessageUpdates(chat: Chat): Flow<T> = filterBaseMessageUpdatesByChatId(chat.id)
|
||||||
|
|
||||||
|
|
||||||
fun <T : SentMediaGroupUpdate> Flow<T>.filterSentMediaGroupUpdates(chatId: ChatId): Flow<T> = filter {
|
/**
|
||||||
it.data.first().chat.id == chatId
|
* [Flow.filter] incoming [SentMediaGroupUpdate]s by their [ChatId]
|
||||||
}
|
*/
|
||||||
fun <T : SentMediaGroupUpdate> Flow<T>.filterSentMediaGroupUpdates(chat: Chat): Flow<T> = filterSentMediaGroupUpdates(chat.id)
|
fun <T : SentMediaGroupUpdate> Flow<T>.filterSentMediaGroupUpdatesByChatId(chatId: ChatId): Flow<T> = filter { it.data.first().chat.id == chatId }
|
||||||
|
/**
|
||||||
|
* [Flow.filter] incoming [SentMediaGroupUpdate]s by their [ChatId] using [Chat.id] of [chat]
|
||||||
|
*/
|
||||||
|
fun <T : SentMediaGroupUpdate> Flow<T>.filterSentMediaGroupUpdatesByChat(chat: Chat): Flow<T> = filterSentMediaGroupUpdatesByChatId(chat.id)
|
||||||
|
/**
|
||||||
|
* [Flow.filter] incoming [SentMediaGroupUpdate]s by their [ChatId]
|
||||||
|
*/
|
||||||
|
@Deprecated("Renamed", ReplaceWith("filterSentMediaGroupUpdatesByChatId"))
|
||||||
|
fun <T : SentMediaGroupUpdate> Flow<T>.filterSentMediaGroupUpdates(chatId: ChatId): Flow<T> = filterSentMediaGroupUpdatesByChatId(chatId)
|
||||||
|
/**
|
||||||
|
* [Flow.filter] incoming [SentMediaGroupUpdate]s by their [ChatId] using [Chat.id] of [chat]
|
||||||
|
*/
|
||||||
|
@Deprecated("Renamed", ReplaceWith("filterSentMediaGroupUpdatesByChat"))
|
||||||
|
fun <T : SentMediaGroupUpdate> Flow<T>.filterSentMediaGroupUpdates(chat: Chat): Flow<T> = filterSentMediaGroupUpdatesByChatId(chat.id)
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.updates
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.MediaGroupIdentifier
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.UpdateIdentifier
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.MediaGroupMessage
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.update.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return If [this] is [SentMediaGroupUpdate] - [Update.updateId] of [last] element, or its own [Update.updateId]
|
||||||
|
*/
|
||||||
|
fun Update.lastUpdateIdentifier(): UpdateIdentifier {
|
||||||
|
return if (this is SentMediaGroupUpdate) {
|
||||||
|
origins.last().updateId
|
||||||
|
} else {
|
||||||
|
updateId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The biggest [UpdateIdentifier] OR null
|
||||||
|
*
|
||||||
|
* @see [Update.lastUpdateIdentifier]
|
||||||
|
*/
|
||||||
|
fun List<Update>.lastUpdateIdentifier(): UpdateIdentifier? {
|
||||||
|
return maxBy { it.updateId } ?.lastUpdateIdentifier()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will convert incoming list of updates to list with [MediaGroupUpdate]s
|
||||||
|
*/
|
||||||
|
fun List<Update>.convertWithMediaGroupUpdates(): List<Update> {
|
||||||
|
val resultUpdates = mutableListOf<Update>()
|
||||||
|
val mediaGroups = mutableMapOf<MediaGroupIdentifier, MutableList<BaseSentMessageUpdate>>()
|
||||||
|
for (update in this) {
|
||||||
|
val data = (update.data as? MediaGroupMessage)
|
||||||
|
if (data == null) {
|
||||||
|
resultUpdates.add(update)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
when (update) {
|
||||||
|
is BaseEditMessageUpdate -> resultUpdates.add(
|
||||||
|
update.toEditMediaGroupUpdate()
|
||||||
|
)
|
||||||
|
is BaseSentMessageUpdate -> {
|
||||||
|
mediaGroups.getOrPut(data.mediaGroupId) {
|
||||||
|
mutableListOf()
|
||||||
|
}.add(update)
|
||||||
|
}
|
||||||
|
else -> resultUpdates.add(update)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mediaGroups.values.map {
|
||||||
|
it.toSentMediaGroupUpdate() ?.let { mediaGroupUpdate ->
|
||||||
|
resultUpdates.add(mediaGroupUpdate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultUpdates.sortBy { it.updateId }
|
||||||
|
return resultUpdates
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @receiver List of [BaseSentMessageUpdate] where [BaseSentMessageUpdate.data] is [MediaGroupMessage] and all messages
|
||||||
|
* have the same [MediaGroupMessage.mediaGroupId]
|
||||||
|
* @return [MessageMediaGroupUpdate] in case if [first] object of [this] is [MessageUpdate]. When [first] object is
|
||||||
|
* [ChannelPostUpdate] instance - will return [ChannelPostMediaGroupUpdate]. Otherwise will be returned null
|
||||||
|
*/
|
||||||
|
fun List<BaseSentMessageUpdate>.toSentMediaGroupUpdate(): SentMediaGroupUpdate? = (this as? SentMediaGroupUpdate) ?: let {
|
||||||
|
if (isEmpty()) {
|
||||||
|
return@let null
|
||||||
|
}
|
||||||
|
val resultList = sortedBy { it.updateId }
|
||||||
|
when (first()) {
|
||||||
|
is MessageUpdate -> MessageMediaGroupUpdate(resultList)
|
||||||
|
is ChannelPostUpdate -> ChannelPostMediaGroupUpdate(resultList)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return [EditMessageMediaGroupUpdate] in case if [this] is [EditMessageUpdate]. When [this] object is
|
||||||
|
* [EditChannelPostUpdate] instance - will return [EditChannelPostMediaGroupUpdate]
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException
|
||||||
|
*/
|
||||||
|
fun BaseEditMessageUpdate.toEditMediaGroupUpdate(): EditMediaGroupUpdate = (this as? EditMediaGroupUpdate) ?: let {
|
||||||
|
when (this) {
|
||||||
|
is EditMessageUpdate -> EditMessageMediaGroupUpdate(this)
|
||||||
|
is EditChannelPostUpdate -> EditChannelPostMediaGroupUpdate(this)
|
||||||
|
else -> error("Unsupported type of ${BaseEditMessageUpdate::class.simpleName}")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,180 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.updates.retrieving
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.bot.RequestsExecutor
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.bot.exceptions.RequestException
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.updates.convertWithMediaGroupUpdates
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.updates.lastUpdateIdentifier
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.requests.GetUpdates
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.update.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.*
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
|
||||||
|
fun RequestsExecutor.startGettingOfUpdatesByLongPolling(
|
||||||
|
timeoutSeconds: Seconds = 30,
|
||||||
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
||||||
|
exceptionsHandler: (ExceptionHandler<Unit>)? = null,
|
||||||
|
allowedUpdates: List<String>? = null,
|
||||||
|
updatesReceiver: UpdateReceiver<Update>
|
||||||
|
): Job = scope.launch {
|
||||||
|
var lastUpdateIdentifier: UpdateIdentifier? = null
|
||||||
|
|
||||||
|
while (isActive) {
|
||||||
|
handleSafely(
|
||||||
|
{ e ->
|
||||||
|
exceptionsHandler ?.invoke(e)
|
||||||
|
if (e is RequestException) {
|
||||||
|
delay(1000L)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
val updates = execute(
|
||||||
|
GetUpdates(
|
||||||
|
offset = lastUpdateIdentifier?.plus(1),
|
||||||
|
timeout = timeoutSeconds,
|
||||||
|
allowed_updates = allowedUpdates
|
||||||
|
)
|
||||||
|
).let { originalUpdates ->
|
||||||
|
val converted = originalUpdates.convertWithMediaGroupUpdates()
|
||||||
|
/**
|
||||||
|
* Dirty hack for cases when the media group was retrieved not fully:
|
||||||
|
*
|
||||||
|
* We are throw out the last media group and will reretrieve it again in the next get updates
|
||||||
|
* and it will guarantee that it is full
|
||||||
|
*/
|
||||||
|
if (originalUpdates.size == getUpdatesLimit.last && converted.last() is SentMediaGroupUpdate) {
|
||||||
|
converted - converted.last()
|
||||||
|
} else {
|
||||||
|
converted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSafely {
|
||||||
|
for (update in updates) {
|
||||||
|
updatesReceiver(update)
|
||||||
|
|
||||||
|
lastUpdateIdentifier = update.lastUpdateIdentifier()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will create a new one [FlowsUpdatesFilter]. This method could be unsafe due to the fact that it will start
|
||||||
|
* getting updates IMMEDIATELY. That means that your bot will be able to skip some of them until you will call
|
||||||
|
* [kotlinx.coroutines.flow.Flow.collect] on one of [FlowsUpdatesFilter] flows. To avoid it, you can pass
|
||||||
|
* [flowUpdatesPreset] lambda - it will be called BEFORE starting updates getting
|
||||||
|
*/
|
||||||
|
@FlowPreview
|
||||||
|
@PreviewFeature
|
||||||
|
@Suppress("unused")
|
||||||
|
fun RequestsExecutor.startGettingFlowsUpdatesByLongPolling(
|
||||||
|
timeoutSeconds: Seconds = 30,
|
||||||
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
||||||
|
exceptionsHandler: ExceptionHandler<Unit>? = null,
|
||||||
|
flowsUpdatesFilterUpdatesKeeperCount: Int = 100,
|
||||||
|
flowUpdatesPreset: FlowsUpdatesFilter.() -> Unit = {}
|
||||||
|
): FlowsUpdatesFilter = FlowsUpdatesFilter(flowsUpdatesFilterUpdatesKeeperCount).apply {
|
||||||
|
flowUpdatesPreset()
|
||||||
|
startGettingOfUpdatesByLongPolling(timeoutSeconds, scope, exceptionsHandler, allowedUpdates, asUpdateReceiver)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun RequestsExecutor.startGettingOfUpdatesByLongPolling(
|
||||||
|
updatesFilter: UpdatesFilter,
|
||||||
|
timeoutSeconds: Seconds = 30,
|
||||||
|
exceptionsHandler: ExceptionHandler<Unit>? = null,
|
||||||
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
||||||
|
): Job = startGettingOfUpdatesByLongPolling(
|
||||||
|
timeoutSeconds,
|
||||||
|
scope,
|
||||||
|
exceptionsHandler,
|
||||||
|
updatesFilter.allowedUpdates,
|
||||||
|
updatesFilter.asUpdateReceiver
|
||||||
|
)
|
||||||
|
|
||||||
|
fun RequestsExecutor.startGettingOfUpdatesByLongPolling(
|
||||||
|
messageCallback: UpdateReceiver<MessageUpdate>? = null,
|
||||||
|
messageMediaGroupCallback: UpdateReceiver<MessageMediaGroupUpdate>? = null,
|
||||||
|
editedMessageCallback: UpdateReceiver<EditMessageUpdate>? = null,
|
||||||
|
editedMessageMediaGroupCallback: UpdateReceiver<EditMessageMediaGroupUpdate>? = null,
|
||||||
|
channelPostCallback: UpdateReceiver<ChannelPostUpdate>? = null,
|
||||||
|
channelPostMediaGroupCallback: UpdateReceiver<ChannelPostMediaGroupUpdate>? = null,
|
||||||
|
editedChannelPostCallback: UpdateReceiver<EditChannelPostUpdate>? = null,
|
||||||
|
editedChannelPostMediaGroupCallback: UpdateReceiver<EditChannelPostMediaGroupUpdate>? = null,
|
||||||
|
chosenInlineResultCallback: UpdateReceiver<ChosenInlineResultUpdate>? = null,
|
||||||
|
inlineQueryCallback: UpdateReceiver<InlineQueryUpdate>? = null,
|
||||||
|
callbackQueryCallback: UpdateReceiver<CallbackQueryUpdate>? = null,
|
||||||
|
shippingQueryCallback: UpdateReceiver<ShippingQueryUpdate>? = null,
|
||||||
|
preCheckoutQueryCallback: UpdateReceiver<PreCheckoutQueryUpdate>? = null,
|
||||||
|
pollCallback: UpdateReceiver<PollUpdate>? = null,
|
||||||
|
pollAnswerCallback: UpdateReceiver<PollAnswerUpdate>? = null,
|
||||||
|
timeoutSeconds: Seconds = 30,
|
||||||
|
exceptionsHandler: ExceptionHandler<Unit>? = null,
|
||||||
|
scope: CoroutineScope = GlobalScope
|
||||||
|
): Job {
|
||||||
|
return startGettingOfUpdatesByLongPolling(
|
||||||
|
SimpleUpdatesFilter(
|
||||||
|
messageCallback,
|
||||||
|
messageMediaGroupCallback,
|
||||||
|
editedMessageCallback,
|
||||||
|
editedMessageMediaGroupCallback,
|
||||||
|
channelPostCallback,
|
||||||
|
channelPostMediaGroupCallback,
|
||||||
|
editedChannelPostCallback,
|
||||||
|
editedChannelPostMediaGroupCallback,
|
||||||
|
chosenInlineResultCallback,
|
||||||
|
inlineQueryCallback,
|
||||||
|
callbackQueryCallback,
|
||||||
|
shippingQueryCallback,
|
||||||
|
preCheckoutQueryCallback,
|
||||||
|
pollCallback,
|
||||||
|
pollAnswerCallback
|
||||||
|
),
|
||||||
|
timeoutSeconds,
|
||||||
|
exceptionsHandler,
|
||||||
|
scope
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
fun RequestsExecutor.startGettingOfUpdatesByLongPolling(
|
||||||
|
messageCallback: UpdateReceiver<MessageUpdate>? = null,
|
||||||
|
mediaGroupCallback: UpdateReceiver<MediaGroupUpdate>? = null,
|
||||||
|
editedMessageCallback: UpdateReceiver<EditMessageUpdate>? = null,
|
||||||
|
channelPostCallback: UpdateReceiver<ChannelPostUpdate>? = null,
|
||||||
|
editedChannelPostCallback: UpdateReceiver<EditChannelPostUpdate>? = null,
|
||||||
|
chosenInlineResultCallback: UpdateReceiver<ChosenInlineResultUpdate>? = null,
|
||||||
|
inlineQueryCallback: UpdateReceiver<InlineQueryUpdate>? = null,
|
||||||
|
callbackQueryCallback: UpdateReceiver<CallbackQueryUpdate>? = null,
|
||||||
|
shippingQueryCallback: UpdateReceiver<ShippingQueryUpdate>? = null,
|
||||||
|
preCheckoutQueryCallback: UpdateReceiver<PreCheckoutQueryUpdate>? = null,
|
||||||
|
pollCallback: UpdateReceiver<PollUpdate>? = null,
|
||||||
|
pollAnswerCallback: UpdateReceiver<PollAnswerUpdate>? = null,
|
||||||
|
timeoutSeconds: Seconds = 30,
|
||||||
|
exceptionsHandler: ExceptionHandler<Unit>? = null,
|
||||||
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
||||||
|
): Job = startGettingOfUpdatesByLongPolling(
|
||||||
|
messageCallback = messageCallback,
|
||||||
|
messageMediaGroupCallback = mediaGroupCallback,
|
||||||
|
editedMessageCallback = editedMessageCallback,
|
||||||
|
editedMessageMediaGroupCallback = mediaGroupCallback,
|
||||||
|
channelPostCallback = channelPostCallback,
|
||||||
|
channelPostMediaGroupCallback = mediaGroupCallback,
|
||||||
|
editedChannelPostCallback = editedChannelPostCallback,
|
||||||
|
editedChannelPostMediaGroupCallback = mediaGroupCallback,
|
||||||
|
chosenInlineResultCallback = chosenInlineResultCallback,
|
||||||
|
inlineQueryCallback = inlineQueryCallback,
|
||||||
|
callbackQueryCallback = callbackQueryCallback,
|
||||||
|
shippingQueryCallback = shippingQueryCallback,
|
||||||
|
preCheckoutQueryCallback = preCheckoutQueryCallback,
|
||||||
|
pollCallback = pollCallback,
|
||||||
|
pollAnswerCallback = pollAnswerCallback,
|
||||||
|
timeoutSeconds = timeoutSeconds,
|
||||||
|
exceptionsHandler = exceptionsHandler,
|
||||||
|
scope = scope
|
||||||
|
)
|
||||||
|
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.updates.retrieving
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.updates.convertWithMediaGroupUpdates
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.MediaGroupMessage
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.BaseMessageUpdate
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.UpdateReceiver
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.extensions.accumulateByKey
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.channels.Channel
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create [UpdateReceiver] object which will correctly accumulate updates and send into output updates which INCLUDE
|
||||||
|
* [com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates.MediaGroupUpdate]s.
|
||||||
|
*
|
||||||
|
* @see UpdateReceiver
|
||||||
|
*/
|
||||||
|
fun CoroutineScope.updateHandlerWithMediaGroupsAdaptation(
|
||||||
|
output: UpdateReceiver<Update>,
|
||||||
|
debounceTimeMillis: Long = 1000L
|
||||||
|
): UpdateReceiver<Update> {
|
||||||
|
val updatesChannel = Channel<Update>(Channel.UNLIMITED)
|
||||||
|
val mediaGroupChannel = Channel<Pair<String, BaseMessageUpdate>>(Channel.UNLIMITED)
|
||||||
|
val mediaGroupAccumulatedChannel = mediaGroupChannel.accumulateByKey(
|
||||||
|
debounceTimeMillis,
|
||||||
|
scope = this
|
||||||
|
)
|
||||||
|
|
||||||
|
launch {
|
||||||
|
launch {
|
||||||
|
for (update in updatesChannel) {
|
||||||
|
when (val data = update.data) {
|
||||||
|
is MediaGroupMessage -> mediaGroupChannel.send("${data.mediaGroupId}${update::class.simpleName}" to update as BaseMessageUpdate)
|
||||||
|
else -> output(update)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
launch {
|
||||||
|
for ((_, mediaGroup) in mediaGroupAccumulatedChannel) {
|
||||||
|
mediaGroup.convertWithMediaGroupUpdates().forEach {
|
||||||
|
output(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { updatesChannel.send(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create [UpdateReceiver] object which will correctly accumulate updates and send into output updates which INCLUDE
|
||||||
|
* [com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates.MediaGroupUpdate]s.
|
||||||
|
*
|
||||||
|
* @see UpdateReceiver
|
||||||
|
*/
|
||||||
|
fun CoroutineScope.updateHandlerWithMediaGroupsAdaptation(
|
||||||
|
output: UpdateReceiver<Update>
|
||||||
|
) = updateHandlerWithMediaGroupsAdaptation(output, 1000L)
|
||||||
@@ -0,0 +1,197 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.updates.retrieving
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.bot.RequestsExecutor
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.nonstrictJsonFormat
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.MultipartFile
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.requests.send.media.base.MultipartRequestImpl
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.requests.webhook.SetWebhook
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.Update
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.update.abstracts.UpdateDeserializationStrategy
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.UpdateReceiver
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.UpdatesFilter
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.webhook.WebhookPrivateKeyConfig
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.ExceptionHandler
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.handleSafely
|
||||||
|
import io.ktor.application.call
|
||||||
|
import io.ktor.request.receiveText
|
||||||
|
import io.ktor.response.respond
|
||||||
|
import io.ktor.routing.*
|
||||||
|
import io.ktor.server.engine.*
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.asCoroutineDispatcher
|
||||||
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to include webhook in custom route everywhere in your server
|
||||||
|
*
|
||||||
|
* @param [scope] Will be used for mapping of media groups
|
||||||
|
* @param [exceptionsHandler] Pass this parameter to set custom exception handler for getting updates
|
||||||
|
* @param [block] Some receiver block like [com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.FlowsUpdatesFilter]
|
||||||
|
*
|
||||||
|
* @see com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.FlowsUpdatesFilter
|
||||||
|
* @see UpdatesFilter
|
||||||
|
* @see UpdatesFilter.asUpdateReceiver
|
||||||
|
*/
|
||||||
|
fun Route.includeWebhookHandlingInRoute(
|
||||||
|
scope: CoroutineScope,
|
||||||
|
exceptionsHandler: ExceptionHandler<Unit>? = null,
|
||||||
|
block: UpdateReceiver<Update>
|
||||||
|
) {
|
||||||
|
val transformer = scope.updateHandlerWithMediaGroupsAdaptation(block)
|
||||||
|
post {
|
||||||
|
handleSafely(
|
||||||
|
exceptionsHandler ?: {}
|
||||||
|
) {
|
||||||
|
val asJson =
|
||||||
|
nonstrictJsonFormat.parseJson(call.receiveText())
|
||||||
|
val update = nonstrictJsonFormat.fromJson(
|
||||||
|
UpdateDeserializationStrategy,
|
||||||
|
asJson
|
||||||
|
)
|
||||||
|
transformer(update)
|
||||||
|
}
|
||||||
|
call.respond("Ok")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setting up ktor server, set webhook info via [SetWebhook] request.
|
||||||
|
*
|
||||||
|
* @param listenPort port which will be listen by bot
|
||||||
|
* @param listenRoute address to listen by bot. If null - will be set up in root of host
|
||||||
|
* @param scope Scope which will be used for
|
||||||
|
* @param privateKeyConfig If configured - server will be created with [sslConnector]. [connector] will be used otherwise
|
||||||
|
*
|
||||||
|
* @see com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.FlowsUpdatesFilter
|
||||||
|
* @see UpdatesFilter
|
||||||
|
* @see UpdatesFilter.asUpdateReceiver
|
||||||
|
*/
|
||||||
|
fun startListenWebhooks(
|
||||||
|
listenPort: Int,
|
||||||
|
engineFactory: ApplicationEngineFactory<*, *>,
|
||||||
|
exceptionsHandler: ExceptionHandler<Unit>,
|
||||||
|
listenHost: String = "0.0.0.0",
|
||||||
|
listenRoute: String? = null,
|
||||||
|
privateKeyConfig: WebhookPrivateKeyConfig? = null,
|
||||||
|
scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()),
|
||||||
|
block: UpdateReceiver<Update>
|
||||||
|
): ApplicationEngine {
|
||||||
|
val env = applicationEngineEnvironment {
|
||||||
|
|
||||||
|
module {
|
||||||
|
routing {
|
||||||
|
listenRoute ?.also {
|
||||||
|
createRouteFromPath(it).includeWebhookHandlingInRoute(scope, exceptionsHandler, block)
|
||||||
|
} ?: includeWebhookHandlingInRoute(scope, exceptionsHandler, block)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
privateKeyConfig ?.let {
|
||||||
|
sslConnector(
|
||||||
|
privateKeyConfig.keyStore,
|
||||||
|
privateKeyConfig.aliasName,
|
||||||
|
privateKeyConfig::keyStorePassword,
|
||||||
|
privateKeyConfig::aliasPassword
|
||||||
|
) {
|
||||||
|
host = listenHost
|
||||||
|
port = listenPort
|
||||||
|
}
|
||||||
|
} ?: connector {
|
||||||
|
host = listenHost
|
||||||
|
port = listenPort
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return embeddedServer(engineFactory, env).also {
|
||||||
|
it.start(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun RequestsExecutor.internalSetWebhookInfoAndStartListenWebhooks(
|
||||||
|
listenPort: Int,
|
||||||
|
engineFactory: ApplicationEngineFactory<*, *>,
|
||||||
|
setWebhookRequest: Request<Boolean>,
|
||||||
|
exceptionsHandler: ExceptionHandler<Unit> = {},
|
||||||
|
listenHost: String = "0.0.0.0",
|
||||||
|
listenRoute: String? = null,
|
||||||
|
privateKeyConfig: WebhookPrivateKeyConfig? = null,
|
||||||
|
scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()),
|
||||||
|
block: UpdateReceiver<Update>
|
||||||
|
): ApplicationEngine {
|
||||||
|
return try {
|
||||||
|
execute(setWebhookRequest)
|
||||||
|
startListenWebhooks(listenPort, engineFactory, exceptionsHandler, listenHost, listenRoute, privateKeyConfig, scope, block)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setting up ktor server, set webhook info via [SetWebhook] request.
|
||||||
|
*
|
||||||
|
* @param listenPort port which will be listen by bot
|
||||||
|
* @param listenRoute address to listen by bot
|
||||||
|
* @param scope Scope which will be used for
|
||||||
|
*
|
||||||
|
* @see com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.FlowsUpdatesFilter
|
||||||
|
* @see UpdatesFilter
|
||||||
|
* @see UpdatesFilter.asUpdateReceiver
|
||||||
|
*/
|
||||||
|
@Suppress("unused")
|
||||||
|
suspend fun RequestsExecutor.setWebhookInfoAndStartListenWebhooks(
|
||||||
|
listenPort: Int,
|
||||||
|
engineFactory: ApplicationEngineFactory<*, *>,
|
||||||
|
setWebhookRequest: SetWebhook,
|
||||||
|
exceptionsHandler: ExceptionHandler<Unit> = {},
|
||||||
|
listenHost: String = "0.0.0.0",
|
||||||
|
listenRoute: String = "/",
|
||||||
|
privateKeyConfig: WebhookPrivateKeyConfig? = null,
|
||||||
|
scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()),
|
||||||
|
block: UpdateReceiver<Update>
|
||||||
|
): ApplicationEngine = internalSetWebhookInfoAndStartListenWebhooks(
|
||||||
|
listenPort,
|
||||||
|
engineFactory,
|
||||||
|
setWebhookRequest as Request<Boolean>,
|
||||||
|
exceptionsHandler,
|
||||||
|
listenHost,
|
||||||
|
listenRoute,
|
||||||
|
privateKeyConfig,
|
||||||
|
scope,
|
||||||
|
block
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setting up ktor server, set webhook info via [SetWebhook] request.
|
||||||
|
*
|
||||||
|
* @param listenPort port which will be listen by bot
|
||||||
|
* @param listenRoute address to listen by bot
|
||||||
|
* @param scope Scope which will be used for
|
||||||
|
*
|
||||||
|
* @see com.github.insanusmokrassar.TelegramBotAPI.updateshandlers.FlowsUpdatesFilter
|
||||||
|
* @see UpdatesFilter
|
||||||
|
* @see UpdatesFilter.asUpdateReceiver
|
||||||
|
*/
|
||||||
|
@Suppress("unused")
|
||||||
|
suspend fun RequestsExecutor.setWebhookInfoAndStartListenWebhooks(
|
||||||
|
listenPort: Int,
|
||||||
|
engineFactory: ApplicationEngineFactory<*, *>,
|
||||||
|
setWebhookRequest: MultipartRequestImpl<SetWebhook, Map<String, MultipartFile>, Boolean>,
|
||||||
|
exceptionsHandler: ExceptionHandler<Unit> = {},
|
||||||
|
listenHost: String = "0.0.0.0",
|
||||||
|
listenRoute: String? = null,
|
||||||
|
privateKeyConfig: WebhookPrivateKeyConfig? = null,
|
||||||
|
scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()),
|
||||||
|
block: UpdateReceiver<Update>
|
||||||
|
): ApplicationEngine = internalSetWebhookInfoAndStartListenWebhooks(
|
||||||
|
listenPort,
|
||||||
|
engineFactory,
|
||||||
|
setWebhookRequest as Request<Boolean>,
|
||||||
|
exceptionsHandler,
|
||||||
|
listenHost,
|
||||||
|
listenRoute,
|
||||||
|
privateKeyConfig,
|
||||||
|
scope,
|
||||||
|
block
|
||||||
|
)
|
||||||
81
TelegramBotAPI.minder
Normal file
81
TelegramBotAPI.minder
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<minder version="1.8.0">
|
||||||
|
<theme name="default" label="Default" index="-1"/>
|
||||||
|
<styles>
|
||||||
|
<style level="0" isset="true" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="200" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true" connectiondash="dotted" connectionwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10"/>
|
||||||
|
<style level="1" isset="true" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="200" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true" connectiondash="dotted" connectionwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10"/>
|
||||||
|
<style level="2" isset="true" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="200" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true" connectiondash="dotted" connectionwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10"/>
|
||||||
|
<style level="3" isset="true" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="200" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true" connectiondash="dotted" connectionwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10"/>
|
||||||
|
<style level="4" isset="true" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="200" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true" connectiondash="dotted" connectionwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10"/>
|
||||||
|
<style level="5" isset="true" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="200" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true" connectiondash="dotted" connectionwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10"/>
|
||||||
|
<style level="6" isset="true" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="200" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true" connectiondash="dotted" connectionwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10"/>
|
||||||
|
<style level="7" isset="true" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="200" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true" connectiondash="dotted" connectionwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10"/>
|
||||||
|
<style level="8" isset="true" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="200" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true" connectiondash="dotted" connectionwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10"/>
|
||||||
|
<style level="9" isset="true" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="200" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true" connectiondash="dotted" connectionwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10"/>
|
||||||
|
<style level="10" isset="true" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="200" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true" connectiondash="dotted" connectionwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10"/>
|
||||||
|
</styles>
|
||||||
|
<drawarea x="-53.566975911458371" y="280.97174580891931" scale="1"/>
|
||||||
|
<images/>
|
||||||
|
<nodes>
|
||||||
|
<node id="1" posx="475.27954101562455" posy="-172.96498107910156" maxwidth="489.29239908854163" width="494" height="168" side="top" fold="false" treesize="724" layout="Downwards">
|
||||||
|
<style linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="200" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true"/>
|
||||||
|
<formatting/>
|
||||||
|
<nodename>TelegramBotAPI
|
||||||
|
|
||||||
|
Root project with API. It is not recommended to use its requests directly and better to use at least TelegramBotAPI-extensions-api</nodename>
|
||||||
|
<nodenote></nodenote>
|
||||||
|
<nodes>
|
||||||
|
<node id="3" posx="568.77954101562455" posy="95.035018920898438" maxwidth="286.41682942708326" width="307" height="168" side="bottom" fold="false" treesize="724" color="#68b723" colorroot="true" layout="Downwards">
|
||||||
|
<style linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="none" nodewidth="200" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true"/>
|
||||||
|
<formatting/>
|
||||||
|
<nodename>TelegramBotAPI-extensions
|
||||||
|
|
||||||
|
Family of projects which are fully based on TelegramBotAPI and extend its functionality</nodename>
|
||||||
|
<nodenote></nodenote>
|
||||||
|
<nodes>
|
||||||
|
<node id="5" posx="360.27954101562455" posy="363.03501892089844" maxwidth="322.17146809895831" width="351" height="191" side="bottom" fold="false" treesize="351" color="#68b723" colorroot="true" layout="Downwards">
|
||||||
|
<style linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="200" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true"/>
|
||||||
|
<formatting/>
|
||||||
|
<nodename>TelegramBotAPI-extensions-api
|
||||||
|
|
||||||
|
Extensions project for make requests more look like in the Telegram Bot API and give opportunity to use it's easier</nodename>
|
||||||
|
<nodenote></nodenote>
|
||||||
|
</node>
|
||||||
|
<node id="7" posx="711.27954101562455" posy="363.03501892089844" maxwidth="341.10636393229163" width="373" height="145" side="bottom" fold="false" treesize="373" color="#68b723" colorroot="true" layout="Downwards">
|
||||||
|
<style linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="200" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true"/>
|
||||||
|
<formatting/>
|
||||||
|
<nodename>TelegramBotAPI-extensions-utils
|
||||||
|
|
||||||
|
Extensions project with utils things which will make easier different operations</nodename>
|
||||||
|
<nodenote></nodenote>
|
||||||
|
</node>
|
||||||
|
</nodes>
|
||||||
|
</node>
|
||||||
|
</nodes>
|
||||||
|
</node>
|
||||||
|
<node id="9" posx="521.83642578124955" posy="645.92375183105469" maxwidth="405.23974609375" width="395" height="213" side="bottom" fold="false" treesize="395" layout="Downwards">
|
||||||
|
<style linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="200" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true"/>
|
||||||
|
<formatting/>
|
||||||
|
<nodename>TelegramBotAPI-all
|
||||||
|
|
||||||
|
Here included all available TelegramBotAPI libraries:
|
||||||
|

|
||||||
|
* TelegramBotAPI
|
||||||
|
* TelegramBotAPI-extensions-api
|
||||||
|
* TelegramBotAPI-extensions-utils</nodename>
|
||||||
|
<nodenote></nodenote>
|
||||||
|
</node>
|
||||||
|
</nodes>
|
||||||
|
<connections>
|
||||||
|
<connection from_id="5" to_id="9" drag_x="574.8447265625" drag_y="605.20840454101562" color="rgb(119,119,119)">
|
||||||
|
<style connectiondash="dotted" connectionwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10"/>
|
||||||
|
<title></title>
|
||||||
|
<note></note>
|
||||||
|
</connection>
|
||||||
|
<connection from_id="7" to_id="9" drag_x="856.732666015625" drag_y="600.25286865234375" color="rgb(119,119,119)">
|
||||||
|
<style connectiondash="dotted" connectionwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10"/>
|
||||||
|
<title></title>
|
||||||
|
<note></note>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</minder>
|
||||||
@@ -10,7 +10,7 @@ moments are describing by official [Telegram Bot API](https://core.telegram.org/
|
|||||||
|
|
||||||
## Compatibility
|
## Compatibility
|
||||||
|
|
||||||
This version compatible with [24th of April 2020 update of TelegramBotAPI (version 4.8)](https://core.telegram.org/bots/api#april-24-2020).
|
This version compatible with [4th of June 2020 update of TelegramBotAPI (version 4.9)](https://core.telegram.org/bots/api#june-4-2020).
|
||||||
There is only one exception of implemented functionality - Telegram Passport API, which was presented in
|
There is only one exception of implemented functionality - Telegram Passport API, which was presented in
|
||||||
[August 2018 update of TelegramBotAPI](https://core.telegram.org/bots/api-changelog#august-27-2018) update. It will be implemented
|
[August 2018 update of TelegramBotAPI](https://core.telegram.org/bots/api-changelog#august-27-2018) update. It will be implemented
|
||||||
as soon as possible.
|
as soon as possible.
|
||||||
@@ -149,53 +149,3 @@ Here was used `okhttp` realisation of client, but there are several others engin
|
|||||||
available on ktor.io site for [client](https://ktor.io/clients/http-client/engines.html) and [server](https://ktor.io/quickstart/artifacts.html)
|
available on ktor.io site for [client](https://ktor.io/clients/http-client/engines.html) and [server](https://ktor.io/quickstart/artifacts.html)
|
||||||
engines.
|
engines.
|
||||||
|
|
||||||
## Getting updates
|
|
||||||
|
|
||||||
In this library currently realised two ways to get updates from telegram:
|
|
||||||
|
|
||||||
* Polling - in this case bot will request updates from time to time (you can set up delay between requests)
|
|
||||||
* Webhook via reverse proxy or something like this
|
|
||||||
|
|
||||||
### Updates filters
|
|
||||||
|
|
||||||
Currently webhook method contains `UpdatesFilter` as necessary argument for getting updates.
|
|
||||||
`UpdatesFilter` will sort updates and throw their into different callbacks. Currently supporting
|
|
||||||
separate getting updates for media groups - they are accumulating with debounce in one second
|
|
||||||
(for being sure that all objects of media group was received).
|
|
||||||
|
|
||||||
Updates polling also support `UpdatesFilter` but it is not required to use it and you can get updates directly
|
|
||||||
in `UpdateReceiver`, which you will provide to `startGettingOfUpdates` method
|
|
||||||
|
|
||||||
### Webhook set up
|
|
||||||
|
|
||||||
If you wish to use webhook method, you will need:
|
|
||||||
|
|
||||||
* White IP - your IP address or host, which available for calling. [TelegramBotAPI](https://core.telegram.org/bots/api#setwebhook)
|
|
||||||
recommend to use some unique address for each bot which you are using
|
|
||||||
* SSL certificate. Usually you can obtain the certificate using your domain provider, [Let'sEncrypt](https://letsencrypt.org/) or [create it](https://core.telegram.org/bots/self-signed)
|
|
||||||
* Nginx or something like this
|
|
||||||
|
|
||||||
Template for Nginx server config you can find in [this gist](https://gist.github.com/InsanusMokrassar/fcc6e09cebd07e46e8f0fdec234750c4#file-nginxssl-conf).
|
|
||||||
|
|
||||||
For webhook you can provide `File` with public part of certificate, `URL` where bot will be available and inner `PORT` which
|
|
||||||
will be used to start receiving of updates. Actually, you can skip passing of `File` when you have something like
|
|
||||||
nginx for proxy forwarding.
|
|
||||||
|
|
||||||
In case of using `nginx` with reverse-proxy config, setting up of Webhook will look like:
|
|
||||||
|
|
||||||
```kotlin
|
|
||||||
requestsExecutor.setWebhook(
|
|
||||||
WEBHOOK_URL,
|
|
||||||
INTERNAL_PORT,
|
|
||||||
filter,
|
|
||||||
ENGINE_FACTORY
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
Here:
|
|
||||||
|
|
||||||
* `WEBHOOK_URL` - the url which will be used by Telegram system to send updates
|
|
||||||
* `INTERNAL_PORT` - the port which will be used in bot for listening of updates
|
|
||||||
* `filter` - instance of [UpdatesFilter](https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/TelegramBotAPI/src/commonMain/kotlin/com/github/insanusmokrassar/TelegramBotAPI/updateshandlers/UpdatesFilter.kt),
|
|
||||||
which will be used to filter incoming updates
|
|
||||||
* `ENGINE_FACTORY` - used factory name, for example, `CIO` in case of usage `io.ktor:ktor-server-cio` as server engine
|
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ kotlin {
|
|||||||
|
|
||||||
api "io.ktor:ktor-server-host-common:$ktor_version"
|
api "io.ktor:ktor-server-host-common:$ktor_version"
|
||||||
api "io.ktor:ktor-client-cio:$ktor_version"
|
api "io.ktor:ktor-client-cio:$ktor_version"
|
||||||
|
|
||||||
|
api "javax.activation:activation:$javax_activation_version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
jvmTest {
|
jvmTest {
|
||||||
@@ -82,7 +84,6 @@ kotlin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
targets.all {
|
targets.all {
|
||||||
compilations.all {
|
compilations.all {
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
|
|||||||
@@ -20,37 +20,33 @@ publishing {
|
|||||||
publications.all {
|
publications.all {
|
||||||
artifact javadocsJar
|
artifact javadocsJar
|
||||||
|
|
||||||
pom.withXml {
|
pom {
|
||||||
asNode().children().last() + {
|
description = "Library for Object-Oriented and type-safe work with Telegram Bot API"
|
||||||
resolveStrategy = Closure.DELEGATE_FIRST
|
name = "Telegram Bot API"
|
||||||
|
url = "https://insanusmokrassar.github.io/TelegramBotAPI"
|
||||||
|
|
||||||
description "Library for Object-Oriented and type-safe work with Telegram Bot API"
|
scm {
|
||||||
name "Telegram Bot API"
|
developerConnection = "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
||||||
url "https://insanusmokrassar.github.io/TelegramBotAPI"
|
url = "https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
||||||
|
}
|
||||||
|
|
||||||
scm {
|
developers {
|
||||||
developerConnection "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
|
||||||
url "https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
developer {
|
||||||
}
|
id = "InsanusMokrassar"
|
||||||
|
name = "Ovsiannikov Aleksei"
|
||||||
|
email = "ovsyannikov.alexey95@gmail.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
developers {
|
licenses {
|
||||||
|
|
||||||
developer {
|
license {
|
||||||
id "InsanusMokrassar"
|
name = "Apache Software License 2.0"
|
||||||
name "Ovsiannikov Aleksei"
|
url = "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
|
||||||
email "ovsyannikov.alexey95@gmail.com"
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
licenses {
|
|
||||||
|
|
||||||
license {
|
|
||||||
name "Apache Software License 2.0"
|
|
||||||
url "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,15 @@ interface CaptionedOutput : Captioned {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface CaptionedInput : Captioned {
|
interface CaptionedInput : Captioned {
|
||||||
|
/**
|
||||||
|
* Not full list of entities. This list WILL NOT contain [TextPart]s with [com.github.insanusmokrassar.TelegramBotAPI.types.MessageEntity.textsources.RegularTextSource]
|
||||||
|
* @see [CaptionedInput.fullEntitiesList]
|
||||||
|
*/
|
||||||
val captionEntities: List<TextPart>
|
val captionEntities: List<TextPart>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert its [CaptionedInput.captionEntities] to list of [com.github.insanusmokrassar.TelegramBotAPI.CommonAbstracts.TextSource]
|
||||||
|
* with [com.github.insanusmokrassar.TelegramBotAPI.types.MessageEntity.textsources.RegularTextSource]
|
||||||
|
*/
|
||||||
fun CaptionedInput.fullEntitiesList(): FullTextSourcesList = caption ?.fullListOfSubSource(captionEntities) ?.map { it.source } ?: emptyList()
|
fun CaptionedInput.fullEntitiesList(): FullTextSourcesList = caption ?.fullListOfSubSource(captionEntities) ?.map { it.source } ?: emptyList()
|
||||||
|
|||||||
@@ -12,7 +12,15 @@ interface ExplainedOutput : Explained {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface ExplainedInput : Explained {
|
interface ExplainedInput : Explained {
|
||||||
|
/**
|
||||||
|
* Not full list of entities. This list WILL NOT contain [TextPart]s with [com.github.insanusmokrassar.TelegramBotAPI.types.MessageEntity.textsources.RegularTextSource]
|
||||||
|
* @see [ExplainedInput.fullEntitiesList]
|
||||||
|
*/
|
||||||
val explanationEntities: List<TextPart>
|
val explanationEntities: List<TextPart>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert its [ExplainedInput.explanationEntities] to list of [com.github.insanusmokrassar.TelegramBotAPI.CommonAbstracts.TextSource]
|
||||||
|
* with [com.github.insanusmokrassar.TelegramBotAPI.types.MessageEntity.textsources.RegularTextSource]
|
||||||
|
*/
|
||||||
fun ExplainedInput.fullEntitiesList(): FullTextSourcesList = explanation ?.fullListOfSubSource(explanationEntities) ?.map { it.source } ?: emptyList()
|
fun ExplainedInput.fullEntitiesList(): FullTextSourcesList = explanation ?.fullListOfSubSource(explanationEntities) ?.map { it.source } ?: emptyList()
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.github.insanusmokrassar.TelegramBotAPI.CommonAbstracts
|
package com.github.insanusmokrassar.TelegramBotAPI.CommonAbstracts
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.MimeType
|
||||||
|
|
||||||
interface MimeTyped {
|
interface MimeTyped {
|
||||||
val mimeType: String? // TODO::replace by something like enum or interface
|
val mimeType: MimeType?
|
||||||
}
|
}
|
||||||
@@ -3,9 +3,20 @@ package com.github.insanusmokrassar.TelegramBotAPI.bot
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
|
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.Request
|
||||||
import io.ktor.utils.io.core.Closeable
|
import io.ktor.utils.io.core.Closeable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for making requests to Telegram Bot API. Currently, there is only one built-in implementation -
|
||||||
|
* [com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor.KtorRequestsExecutor]
|
||||||
|
*
|
||||||
|
* @see Request
|
||||||
|
* @see com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor.KtorRequestsExecutor
|
||||||
|
*/
|
||||||
interface RequestsExecutor : Closeable {
|
interface RequestsExecutor : Closeable {
|
||||||
/**
|
/**
|
||||||
* @throws com.github.insanusmokrassar.TelegramBotAPI.bot.exceptions.RequestException
|
* Unsafe execution of incoming [request]. Can throw almost any exception. So, it is better to use
|
||||||
|
* something like [com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.shortcuts.executeAsync] or
|
||||||
|
* [com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.shortcuts.executeUnsafe]
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
suspend fun <T : Any> execute(request: Request<T>): T
|
suspend fun <T : Any> execute(request: Request<T>): T
|
||||||
}
|
}
|
||||||
@@ -11,6 +11,15 @@ private val updatesListSerializer = ListSerializer(
|
|||||||
UpdateSerializerWithoutSerialization
|
UpdateSerializerWithoutSerialization
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request updates from Telegram Bot API system. It is important, that the result updates WILL NOT include
|
||||||
|
* [com.github.insanusmokrassar.TelegramBotAPI.types.update.MediaGroupUpdates.MediaGroupUpdate] objects due to the fact,
|
||||||
|
* that it is internal abstraction and in fact any [com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.MediaGroupMessage]
|
||||||
|
* is just a common [com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Message]
|
||||||
|
*
|
||||||
|
* @see com.github.insanusmokrassar.TelegramBotAPI.extensions.utils.updates.retrieving.updateHandlerWithMediaGroupsAdaptation
|
||||||
|
* @see com.github.insanusmokrassar.TelegramBotAPI.utils.convertWithMediaGroupUpdates
|
||||||
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
data class GetUpdates(
|
data class GetUpdates(
|
||||||
val offset: UpdateIdentifier? = null,// set `last update id + 1` to receive next part of updates
|
val offset: UpdateIdentifier? = null,// set `last update id + 1` to receive next part of updates
|
||||||
|
|||||||
@@ -5,11 +5,6 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.*
|
|||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
import kotlinx.serialization.builtins.serializer
|
import kotlinx.serialization.builtins.serializer
|
||||||
|
|
||||||
/**
|
|
||||||
* Representation of https://core.telegram.org/bots/api#setchatadministratorcustomtitle
|
|
||||||
*
|
|
||||||
* Please, remember about restrictions for characters in custom title
|
|
||||||
*/
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class SetChatAdministratorCustomTitle(
|
data class SetChatAdministratorCustomTitle(
|
||||||
@SerialName(chatIdField)
|
@SerialName(chatIdField)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.TextContent
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.TextContent
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.throwRangeError
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
internal val TextContentMessageResultDeserializer: DeserializationStrategy<ContentMessage<TextContent>>
|
internal val TextContentMessageResultDeserializer: DeserializationStrategy<ContentMessage<TextContent>>
|
||||||
@@ -37,7 +38,7 @@ data class SendTextMessage(
|
|||||||
{
|
{
|
||||||
init {
|
init {
|
||||||
if (text.length !in textLength) {
|
if (text.length !in textLength) {
|
||||||
throw IllegalArgumentException("Text must be in $textLength range")
|
throwRangeError("Text length", textLength, text.length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.VenueContent
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.VenueContent
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.venue.Venue
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
private val commonResultDeserializer: DeserializationStrategy<ContentMessage<VenueContent>>
|
private val commonResultDeserializer: DeserializationStrategy<ContentMessage<VenueContent>>
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Conten
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.AnimationContent
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.AnimationContent
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.utils.mapOfNotNull
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.mapOfNotNull
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.throwRangeError
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
fun SendAnimation(
|
fun SendAnimation(
|
||||||
@@ -93,7 +94,7 @@ data class SendAnimationData internal constructor(
|
|||||||
init {
|
init {
|
||||||
text ?.let {
|
text ?.let {
|
||||||
if (it.length !in captionLength) {
|
if (it.length !in captionLength) {
|
||||||
throw IllegalArgumentException("Caption must be in $captionLength range")
|
throwRangeError("Caption length", captionLength, it.length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Conten
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.AudioContent
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.AudioContent
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.utils.mapOfNotNull
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.mapOfNotNull
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.throwRangeError
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
fun SendAudio(
|
fun SendAudio(
|
||||||
@@ -95,7 +96,7 @@ data class SendAudioData internal constructor(
|
|||||||
init {
|
init {
|
||||||
text ?.let {
|
text ?.let {
|
||||||
if (it.length !in captionLength) {
|
if (it.length !in captionLength) {
|
||||||
throw IllegalArgumentException("Caption must be in $captionLength range")
|
throwRangeError("Caption length", captionLength, it.length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Conten
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.DocumentContent
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.DocumentContent
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.utils.mapOfNotNull
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.mapOfNotNull
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.throwRangeError
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
fun SendDocument(
|
fun SendDocument(
|
||||||
@@ -79,7 +80,7 @@ data class SendDocumentData internal constructor(
|
|||||||
init {
|
init {
|
||||||
text ?.let {
|
text ?.let {
|
||||||
if (it.length !in captionLength) {
|
if (it.length !in captionLength) {
|
||||||
throw IllegalArgumentException("Caption must be in $captionLength range")
|
throwRangeError("Caption length", captionLength, it.length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,12 +8,15 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.*
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.InputMedia.*
|
import com.github.insanusmokrassar.TelegramBotAPI.types.InputMedia.*
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.MediaGroupMessage
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.MediaGroupMessage
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializeOnlySerializerClass
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializeOnlySerializerClass
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.throwRangeError
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.utils.toJsonWithoutNulls
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.toJsonWithoutNulls
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
import kotlinx.serialization.builtins.ListSerializer
|
import kotlinx.serialization.builtins.ListSerializer
|
||||||
import kotlinx.serialization.json.jsonArray
|
import kotlinx.serialization.json.jsonArray
|
||||||
|
|
||||||
val membersCountInMediaGroup: IntRange = 2 .. 10
|
@Deprecated("Replaced and renamed", ReplaceWith("mediaCountInMediaGroup", "com.github.insanusmokrassar.TelegramBotAPI.types.mediaCountInMediaGroup"))
|
||||||
|
val membersCountInMediaGroup
|
||||||
|
get() = mediaCountInMediaGroup
|
||||||
|
|
||||||
fun SendMediaGroup(
|
fun SendMediaGroup(
|
||||||
chatId: ChatIdentifier,
|
chatId: ChatIdentifier,
|
||||||
@@ -21,8 +24,8 @@ fun SendMediaGroup(
|
|||||||
disableNotification: Boolean = false,
|
disableNotification: Boolean = false,
|
||||||
replyToMessageId: MessageIdentifier? = null
|
replyToMessageId: MessageIdentifier? = null
|
||||||
): Request<List<MediaGroupMessage>> {
|
): Request<List<MediaGroupMessage>> {
|
||||||
if (media.size !in membersCountInMediaGroup) {
|
if (media.size !in mediaCountInMediaGroup) {
|
||||||
throw IllegalArgumentException("Count of members for media group must be in $membersCountInMediaGroup range")
|
throwRangeError("Count of members in media group", mediaCountInMediaGroup, media.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
val files: List<MultipartFile> = media.flatMap {
|
val files: List<MultipartFile> = media.flatMap {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.KeyboardMarkup
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.ContentMessage
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.PhotoContent
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.PhotoContent
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.throwRangeError
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
fun SendPhoto(
|
fun SendPhoto(
|
||||||
@@ -65,7 +66,7 @@ data class SendPhotoData internal constructor(
|
|||||||
init {
|
init {
|
||||||
text ?.let {
|
text ?.let {
|
||||||
if (it.length !in captionLength) {
|
if (it.length !in captionLength) {
|
||||||
throw IllegalArgumentException("Caption must be in $captionLength range")
|
throwRangeError("Caption length", captionLength, it.length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Conten
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.VideoContent
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.VideoContent
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.utils.mapOfNotNull
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.mapOfNotNull
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.throwRangeError
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
fun SendVideo(
|
fun SendVideo(
|
||||||
@@ -97,7 +98,7 @@ data class SendVideoData internal constructor(
|
|||||||
init {
|
init {
|
||||||
text ?.let {
|
text ?.let {
|
||||||
if (it.length !in captionLength) {
|
if (it.length !in captionLength) {
|
||||||
throw IllegalArgumentException("Caption must be in $captionLength range")
|
throwRangeError("Caption length", captionLength, it.length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Conten
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.VideoNoteContent
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.VideoNoteContent
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.utils.mapOfNotNull
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.mapOfNotNull
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.throwRangeError
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
fun SendVideoNote(
|
fun SendVideoNote(
|
||||||
@@ -92,7 +93,7 @@ data class SendVideoNoteData internal constructor(
|
|||||||
init {
|
init {
|
||||||
text ?.let {
|
text ?.let {
|
||||||
if (it.length !in captionLength) {
|
if (it.length !in captionLength) {
|
||||||
throw IllegalArgumentException("Caption must be in $captionLength range")
|
throwRangeError("Caption length", captionLength, it.length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Conten
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.VoiceContent
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.media.VoiceContent
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.utils.mapOfNotNull
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.mapOfNotNull
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.throwRangeError
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
fun SendVoice(
|
fun SendVoice(
|
||||||
@@ -84,7 +85,7 @@ data class SendVoiceData internal constructor(
|
|||||||
init {
|
init {
|
||||||
text ?.let {
|
text ?.let {
|
||||||
if (it.length !in captionLength) {
|
if (it.length !in captionLength) {
|
||||||
throw IllegalArgumentException("Caption must be in $captionLength range")
|
throwRangeError("Caption length", captionLength, it.length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,6 @@ import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.*
|
|||||||
import kotlinx.serialization.DeserializationStrategy
|
import kotlinx.serialization.DeserializationStrategy
|
||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
|
|
||||||
/**
|
|
||||||
* Will be used as SimpleRequest if
|
|
||||||
*/
|
|
||||||
class MultipartRequestImpl<D: DataRequest<R>, F: Files, R: Any>(
|
class MultipartRequestImpl<D: DataRequest<R>, F: Files, R: Any>(
|
||||||
val data: D,
|
val data: D,
|
||||||
val files: F
|
val files: F
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ fun Poll.createRequest(
|
|||||||
correctOptionId,
|
correctOptionId,
|
||||||
isAnonymous,
|
isAnonymous,
|
||||||
isClosed,
|
isClosed,
|
||||||
caption ?.fullListOfSubSource(captionEntities) ?.justTextSources() ?.toMarkdownV2Captions() ?.firstOrNull(),
|
explanation ?.fullListOfSubSource(explanationEntities) ?.justTextSources() ?.toMarkdownV2Captions() ?.firstOrNull(),
|
||||||
MarkdownV2,
|
MarkdownV2,
|
||||||
scheduledCloseInfo,
|
scheduledCloseInfo,
|
||||||
disableNotification,
|
disableNotification,
|
||||||
|
|||||||
@@ -7,33 +7,56 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.*
|
|||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
import kotlinx.serialization.builtins.serializer
|
import kotlinx.serialization.builtins.serializer
|
||||||
|
|
||||||
|
private fun correctWebhookUrl(sourceUrl: String) = if (sourceUrl.contains("://")) {
|
||||||
|
sourceUrl
|
||||||
|
} else {
|
||||||
|
"https://$sourceUrl"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun SetWebhook(
|
||||||
|
url: String,
|
||||||
|
certificate: MultipartFile,
|
||||||
|
maxAllowedConnections: Int? = null,
|
||||||
|
allowedUpdates: List<String>? = null
|
||||||
|
): MultipartRequestImpl<SetWebhook, Map<String, MultipartFile>, Boolean> = MultipartRequestImpl(
|
||||||
|
SetWebhook(
|
||||||
|
correctWebhookUrl(url),
|
||||||
|
null,
|
||||||
|
maxAllowedConnections,
|
||||||
|
allowedUpdates
|
||||||
|
),
|
||||||
|
mapOf(certificateField to certificate)
|
||||||
|
)
|
||||||
|
|
||||||
|
fun SetWebhook(
|
||||||
|
url: String,
|
||||||
|
certificate: FileId,
|
||||||
|
maxAllowedConnections: Int? = null,
|
||||||
|
allowedUpdates: List<String>? = null
|
||||||
|
): SetWebhook = SetWebhook(
|
||||||
|
correctWebhookUrl(url),
|
||||||
|
certificate.fileId,
|
||||||
|
maxAllowedConnections,
|
||||||
|
allowedUpdates
|
||||||
|
)
|
||||||
|
|
||||||
|
@Suppress("USELESS_CAST")
|
||||||
fun SetWebhook(
|
fun SetWebhook(
|
||||||
url: String,
|
url: String,
|
||||||
certificate: InputFile,
|
certificate: InputFile,
|
||||||
maxAllowedConnections: Int? = null,
|
maxAllowedConnections: Int? = null,
|
||||||
allowedUpdates: List<String>? = null
|
allowedUpdates: List<String>? = null
|
||||||
) : Request<Boolean> {
|
): Request<Boolean> = when (certificate) {
|
||||||
val data = SetWebhook(
|
is MultipartFile -> SetWebhook(correctWebhookUrl(url), certificate as MultipartFile, maxAllowedConnections, allowedUpdates)
|
||||||
url,
|
is FileId -> SetWebhook(correctWebhookUrl(url), certificate as FileId, maxAllowedConnections, allowedUpdates)
|
||||||
(certificate as? FileId) ?.fileId,
|
|
||||||
maxAllowedConnections,
|
|
||||||
allowedUpdates
|
|
||||||
)
|
|
||||||
return when (certificate) {
|
|
||||||
is FileId -> data
|
|
||||||
is MultipartFile -> MultipartRequestImpl(
|
|
||||||
data,
|
|
||||||
mapOf(certificateField to certificate)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun SetWebhook(
|
fun SetWebhook(
|
||||||
url: String,
|
url: String,
|
||||||
maxAllowedConnections: Int? = null,
|
maxAllowedConnections: Int? = null,
|
||||||
allowedUpdates: List<String>? = null
|
allowedUpdates: List<String>? = null
|
||||||
) : Request<Boolean> = SetWebhook(
|
) = SetWebhook(
|
||||||
url,
|
correctWebhookUrl(url),
|
||||||
null,
|
null,
|
||||||
maxAllowedConnections,
|
maxAllowedConnections,
|
||||||
allowedUpdates
|
allowedUpdates
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
package com.github.insanusmokrassar.TelegramBotAPI.types
|
package com.github.insanusmokrassar.TelegramBotAPI.types
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.throwRangeError
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
val BotCommandNameRegex = Regex("^[a-z_0-9]{${botCommandLengthLimit.first},${botCommandLengthLimit.last}}$")
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class BotCommand(
|
data class BotCommand(
|
||||||
@SerialName(botCommandField)
|
@SerialName(botCommandField)
|
||||||
@@ -12,10 +15,13 @@ data class BotCommand(
|
|||||||
) {
|
) {
|
||||||
init {
|
init {
|
||||||
if (command.length !in botCommandLengthLimit) {
|
if (command.length !in botCommandLengthLimit) {
|
||||||
error("Command size must be in range $botCommandLengthLimit, but actually have length ${command.length}")
|
throwRangeError("Command name size", botCommandLengthLimit, command.length)
|
||||||
|
}
|
||||||
|
if (!command.matches(BotCommandNameRegex)) {
|
||||||
|
error("Bot command must contains only lowercase English letters, digits and underscores, but incoming command was $command")
|
||||||
}
|
}
|
||||||
if (description.length !in botCommandDescriptionLimit) {
|
if (description.length !in botCommandDescriptionLimit) {
|
||||||
error("Command description size must be in range $botCommandDescriptionLimit, but actually have length ${description.length}")
|
throwRangeError("Command description size", botCommandDescriptionLimit, description.length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.github.insanusmokrassar.TelegramBotAPI.types
|
package com.github.insanusmokrassar.TelegramBotAPI.types
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.BuiltinMimeTypes
|
||||||
|
|
||||||
typealias Identifier = Long
|
typealias Identifier = Long
|
||||||
typealias MessageIdentifier = Long
|
typealias MessageIdentifier = Long
|
||||||
typealias InlineQueryIdentifier = String
|
typealias InlineQueryIdentifier = String
|
||||||
@@ -20,14 +22,16 @@ typealias PollIdentifier = String
|
|||||||
typealias StickerSetName = String
|
typealias StickerSetName = String
|
||||||
typealias FileUniqueId = String
|
typealias FileUniqueId = String
|
||||||
typealias DiceResult = Int
|
typealias DiceResult = Int
|
||||||
|
typealias FoursquareId = String
|
||||||
|
typealias FoursquareType = String
|
||||||
|
|
||||||
typealias Seconds = Int
|
typealias Seconds = Int
|
||||||
typealias LongSeconds = Long
|
typealias LongSeconds = Long
|
||||||
|
|
||||||
val getUpdatesLimit = 1 .. 100
|
val getUpdatesLimit = 1 .. 100
|
||||||
val callbackQueryAnswerLength = 0 until 200
|
val callbackQueryAnswerLength = 0 until 200
|
||||||
val captionLength = 0 until 1024
|
val captionLength = 0 .. 1024
|
||||||
val textLength = 0 until 4096
|
val textLength = 1 .. 4096
|
||||||
val userProfilePhotosRequestLimit = 0 .. 100
|
val userProfilePhotosRequestLimit = 0 .. 100
|
||||||
val chatTitleLength = 1 until 255
|
val chatTitleLength = 1 until 255
|
||||||
val chatDescriptionLength = 0 until 256
|
val chatDescriptionLength = 0 until 256
|
||||||
@@ -55,12 +59,20 @@ val botCommandLimit = botCommandLengthLimit
|
|||||||
val botCommandDescriptionLimit = 3 .. 256
|
val botCommandDescriptionLimit = 3 .. 256
|
||||||
val botCommandsLimit = 0 .. 100
|
val botCommandsLimit = 0 .. 100
|
||||||
|
|
||||||
|
val mediaCountInMediaGroup: IntRange = 2 .. 10
|
||||||
|
|
||||||
val explanationLimit = 0 .. 200
|
val explanationLimit = 0 .. 200
|
||||||
@Deprecated("Will be removed in near updates", ReplaceWith("explanationLimit"))
|
@Deprecated("Will be removed in near updates", ReplaceWith("explanationLimit"))
|
||||||
val quizPollExplanationLimit = explanationLimit
|
val quizPollExplanationLimit = explanationLimit
|
||||||
|
|
||||||
val openPeriodPollSecondsLimit = 5 .. 600
|
val openPeriodPollSecondsLimit = 5 .. 600
|
||||||
|
|
||||||
|
val telegramInlineModeGifPermittedMimeTypes = listOf(
|
||||||
|
BuiltinMimeTypes.Image.Jpg,
|
||||||
|
BuiltinMimeTypes.Image.Gif,
|
||||||
|
BuiltinMimeTypes.Video.MP4
|
||||||
|
)
|
||||||
|
|
||||||
const val chatIdField = "chat_id"
|
const val chatIdField = "chat_id"
|
||||||
const val messageIdField = "message_id"
|
const val messageIdField = "message_id"
|
||||||
const val updateIdField = "update_id"
|
const val updateIdField = "update_id"
|
||||||
@@ -175,6 +187,7 @@ const val stickerFileIdField = "sticker_file_id"
|
|||||||
const val gameShortNameField = "game_short_name"
|
const val gameShortNameField = "game_short_name"
|
||||||
|
|
||||||
const val thumbUrlField = "thumb_url"
|
const val thumbUrlField = "thumb_url"
|
||||||
|
const val thumbMimeTypeField = "thumb_mime_type"
|
||||||
const val thumbWidthField = "thumb_width"
|
const val thumbWidthField = "thumb_width"
|
||||||
const val thumbHeightField = "thumb_height"
|
const val thumbHeightField = "thumb_height"
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.ParseMode
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.parseModeField
|
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.parseModeField
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
|
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.files.abstracts.mimeTypeField
|
import com.github.insanusmokrassar.TelegramBotAPI.types.files.abstracts.mimeTypeField
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.MimeType
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@ data class InlineQueryResultDocumentImpl(
|
|||||||
@SerialName(titleField)
|
@SerialName(titleField)
|
||||||
override val title: String,
|
override val title: String,
|
||||||
@SerialName(mimeTypeField)
|
@SerialName(mimeTypeField)
|
||||||
override val mimeType: String,
|
override val mimeType: MimeType,
|
||||||
@SerialName(thumbUrlField)
|
@SerialName(thumbUrlField)
|
||||||
override val thumbUrl: String? = null,
|
override val thumbUrl: String? = null,
|
||||||
@SerialName(thumbWidthField)
|
@SerialName(thumbWidthField)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.abstracts.
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.ParseMode
|
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.ParseMode
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.parseModeField
|
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.parseModeField
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
|
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.MimeType
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@@ -18,6 +19,8 @@ data class InlineQueryResultGifImpl(
|
|||||||
override val url: String,
|
override val url: String,
|
||||||
@SerialName(thumbUrlField)
|
@SerialName(thumbUrlField)
|
||||||
override val thumbUrl: String,
|
override val thumbUrl: String,
|
||||||
|
@SerialName(thumbMimeTypeField)
|
||||||
|
override val thumbMimeType: MimeType? = null,
|
||||||
@SerialName(gifWidthField)
|
@SerialName(gifWidthField)
|
||||||
override val width: Int? = null,
|
override val width: Int? = null,
|
||||||
@SerialName(gifHeightField)
|
@SerialName(gifHeightField)
|
||||||
@@ -36,4 +39,10 @@ data class InlineQueryResultGifImpl(
|
|||||||
override val inputMessageContent: InputMessageContent? = null
|
override val inputMessageContent: InputMessageContent? = null
|
||||||
) : InlineQueryResultGif {
|
) : InlineQueryResultGif {
|
||||||
override val type: String = inlineQueryResultGifType
|
override val type: String = inlineQueryResultGifType
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (thumbMimeType != null && thumbMimeType !in telegramInlineModeGifPermittedMimeTypes) {
|
||||||
|
error("Passed thumb mime type is not permitted in Telegram Bot API. Passed $thumbMimeType, but permitted $telegramInlineModeGifPermittedMimeTypes")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.abstracts.
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.ParseMode
|
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.ParseMode
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.parseModeField
|
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.parseModeField
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
|
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.MimeType
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@@ -18,6 +19,8 @@ data class InlineQueryResultMpeg4GifImpl(
|
|||||||
override val url: String,
|
override val url: String,
|
||||||
@SerialName(thumbUrlField)
|
@SerialName(thumbUrlField)
|
||||||
override val thumbUrl: String,
|
override val thumbUrl: String,
|
||||||
|
@SerialName(thumbMimeTypeField)
|
||||||
|
override val thumbMimeType: MimeType? = null,
|
||||||
@SerialName(mpeg4GifWidthField)
|
@SerialName(mpeg4GifWidthField)
|
||||||
override val width: Int? = null,
|
override val width: Int? = null,
|
||||||
@SerialName(mpeg4GifHeightField)
|
@SerialName(mpeg4GifHeightField)
|
||||||
@@ -36,4 +39,10 @@ data class InlineQueryResultMpeg4GifImpl(
|
|||||||
override val inputMessageContent: InputMessageContent? = null
|
override val inputMessageContent: InputMessageContent? = null
|
||||||
) : InlineQueryResultMpeg4Gif {
|
) : InlineQueryResultMpeg4Gif {
|
||||||
override val type: String = inlineQueryResultMpeg4GifType
|
override val type: String = inlineQueryResultMpeg4GifType
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (thumbMimeType != null && thumbMimeType !in telegramInlineModeGifPermittedMimeTypes) {
|
||||||
|
error("Passed thumb mime type is not permitted in Telegram Bot API. Passed $thumbMimeType, but permitted $telegramInlineModeGifPermittedMimeTypes")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.ParseMode
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.parseModeField
|
import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.parseModeField
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
|
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.files.abstracts.mimeTypeField
|
import com.github.insanusmokrassar.TelegramBotAPI.types.files.abstracts.mimeTypeField
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.MimeType
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@ data class InlineQueryResultVideoImpl(
|
|||||||
@SerialName(thumbUrlField)
|
@SerialName(thumbUrlField)
|
||||||
override val thumbUrl: String,
|
override val thumbUrl: String,
|
||||||
@SerialName(mimeTypeField)
|
@SerialName(mimeTypeField)
|
||||||
override val mimeType: String,
|
override val mimeType: MimeType,
|
||||||
@SerialName(titleField)
|
@SerialName(titleField)
|
||||||
override val title: String,
|
override val title: String,
|
||||||
@SerialName(videoWidthField)
|
@SerialName(videoWidthField)
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
package com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.InlineQueryResult.abstracts
|
package com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.InlineQueryResult.abstracts
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.MimeType
|
||||||
|
|
||||||
interface ThumbedInlineQueryResult : InlineQueryResult {
|
interface ThumbedInlineQueryResult : InlineQueryResult {
|
||||||
val thumbUrl: String?
|
val thumbUrl: String?
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ThumbedWithMimeTypeInlineQueryResult : ThumbedInlineQueryResult {
|
||||||
|
val thumbMimeType: MimeType?
|
||||||
}
|
}
|
||||||
@@ -2,4 +2,4 @@ package com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.InlineQue
|
|||||||
|
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.InlineQueryResult.abstracts.*
|
import com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.InlineQueryResult.abstracts.*
|
||||||
|
|
||||||
interface InlineQueryResultGif : InlineQueryResultGifCommon, UrlInlineQueryResult, ThumbedInlineQueryResult, SizedInlineQueryResult, DuratedInlineResultQuery
|
interface InlineQueryResultGif : InlineQueryResultGifCommon, UrlInlineQueryResult, ThumbedWithMimeTypeInlineQueryResult, SizedInlineQueryResult, DuratedInlineResultQuery
|
||||||
@@ -2,4 +2,4 @@ package com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.InlineQue
|
|||||||
|
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.InlineQueryResult.abstracts.*
|
import com.github.insanusmokrassar.TelegramBotAPI.types.InlineQueries.InlineQueryResult.abstracts.*
|
||||||
|
|
||||||
interface InlineQueryResultMpeg4Gif : InlineQueryResultMpeg4GifCommon, UrlInlineQueryResult, ThumbedInlineQueryResult, SizedInlineQueryResult, DuratedInlineResultQuery
|
interface InlineQueryResultMpeg4Gif : InlineQueryResultMpeg4GifCommon, UrlInlineQueryResult, ThumbedWithMimeTypeInlineQueryResult, SizedInlineQueryResult, DuratedInlineResultQuery
|
||||||
@@ -7,6 +7,8 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.files.PhotoSize
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.mediaField
|
import com.github.insanusmokrassar.TelegramBotAPI.types.mediaField
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
|
internal const val photoInputMediaType = "photo"
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class InputMediaPhoto(
|
data class InputMediaPhoto(
|
||||||
override val file: InputFile,
|
override val file: InputFile,
|
||||||
@@ -14,7 +16,7 @@ data class InputMediaPhoto(
|
|||||||
@SerialName(parseModeField)
|
@SerialName(parseModeField)
|
||||||
override val parseMode: ParseMode? = null
|
override val parseMode: ParseMode? = null
|
||||||
) : InputMedia, MediaGroupMemberInputMedia {
|
) : InputMedia, MediaGroupMemberInputMedia {
|
||||||
override val type: String = "photo"
|
override val type: String = photoInputMediaType
|
||||||
|
|
||||||
override fun serialize(format: StringFormat): String = format.stringify(serializer(), this)
|
override fun serialize(format: StringFormat): String = format.stringify(serializer(), this)
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.ParseMode.parseModeField
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.mediaField
|
import com.github.insanusmokrassar.TelegramBotAPI.types.mediaField
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
|
internal const val videoInputMediaType = "video"
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class InputMediaVideo(
|
data class InputMediaVideo(
|
||||||
override val file: InputFile,
|
override val file: InputFile,
|
||||||
@@ -17,7 +19,7 @@ data class InputMediaVideo(
|
|||||||
override val duration: Long? = null,
|
override val duration: Long? = null,
|
||||||
override val thumb: InputFile? = null
|
override val thumb: InputFile? = null
|
||||||
) : InputMedia, SizedInputMedia, DuratedInputMedia, ThumbedInputMedia, MediaGroupMemberInputMedia {
|
) : InputMedia, SizedInputMedia, DuratedInputMedia, ThumbedInputMedia, MediaGroupMemberInputMedia {
|
||||||
override val type: String = "video"
|
override val type: String = videoInputMediaType
|
||||||
|
|
||||||
override fun serialize(format: StringFormat): String = format.stringify(serializer(), this)
|
override fun serialize(format: StringFormat): String = format.stringify(serializer(), this)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package com.github.insanusmokrassar.TelegramBotAPI.types.InputMedia
|
package com.github.insanusmokrassar.TelegramBotAPI.types.InputMedia
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.typeField
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.nonstrictJsonFormat
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
|
import kotlinx.serialization.json.JsonObjectSerializer
|
||||||
|
|
||||||
@Serializer(MediaGroupMemberInputMedia::class)
|
@Serializer(MediaGroupMemberInputMedia::class)
|
||||||
internal object MediaGroupMemberInputMediaSerializer : KSerializer<MediaGroupMemberInputMedia> {
|
internal object MediaGroupMemberInputMediaSerializer : KSerializer<MediaGroupMemberInputMedia> {
|
||||||
@@ -13,6 +16,12 @@ internal object MediaGroupMemberInputMediaSerializer : KSerializer<MediaGroupMem
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun deserialize(decoder: Decoder): MediaGroupMemberInputMedia {
|
override fun deserialize(decoder: Decoder): MediaGroupMemberInputMedia {
|
||||||
TODO("not implemented")
|
val json = JsonObjectSerializer.deserialize(decoder)
|
||||||
|
|
||||||
|
return when (json.getPrimitiveOrNull(typeField) ?.contentOrNull) {
|
||||||
|
photoInputMediaType -> nonstrictJsonFormat.fromJson(InputMediaPhoto.serializer(), json)
|
||||||
|
videoInputMediaType -> nonstrictJsonFormat.fromJson(InputMediaVideo.serializer(), json)
|
||||||
|
else -> error("Illegal type of incoming MediaGroupMemberInputMedia")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,6 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.thumbField
|
|||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
// TODO:: fill thumbed
|
|
||||||
interface ThumbedInputMedia : InputMedia {
|
interface ThumbedInputMedia : InputMedia {
|
||||||
val thumb: InputFile?
|
val thumb: InputFile?
|
||||||
@Serializable
|
@Serializable
|
||||||
|
|||||||
@@ -1,19 +1,6 @@
|
|||||||
package com.github.insanusmokrassar.TelegramBotAPI.types
|
package com.github.insanusmokrassar.TelegramBotAPI.types
|
||||||
|
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.CommonAbstracts.CommonVenueData
|
import com.github.insanusmokrassar.TelegramBotAPI.types.venue.Venue
|
||||||
import kotlinx.serialization.SerialName
|
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
|
|
||||||
@Serializable
|
@Deprecated("Replaced", ReplaceWith("Venue", "com.github.insanusmokrassar.TelegramBotAPI.types.venue.Venue"))
|
||||||
data class Venue(
|
typealias Venue = Venue
|
||||||
@SerialName(locationField)
|
|
||||||
val location: Location,
|
|
||||||
@SerialName(titleField)
|
|
||||||
override val title: String,
|
|
||||||
@SerialName(addressField)
|
|
||||||
override val address: String,
|
|
||||||
@SerialName(foursquareIdField)
|
|
||||||
override val foursquareId: String? = null,
|
|
||||||
@SerialName(foursquareTypeField)
|
|
||||||
override val foursquareType: String? = null
|
|
||||||
) : CommonVenueData
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ data class WebhookInfo(
|
|||||||
@SerialName(urlField)
|
@SerialName(urlField)
|
||||||
val url: String,
|
val url: String,
|
||||||
@SerialName(pendingUpdateCountField)
|
@SerialName(pendingUpdateCountField)
|
||||||
val awaitDeliery: Int,
|
val awaitDelivery: Int,
|
||||||
@SerialName(maxAllowedConnectionsField)
|
@SerialName(maxAllowedConnectionsField)
|
||||||
val maxConnections: Int = 40, // default count according to documentation
|
val maxConnections: Int = 40, // default count according to documentation
|
||||||
@SerialName(hasCustomCertificateField)
|
@SerialName(hasCustomCertificateField)
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ package com.github.insanusmokrassar.TelegramBotAPI.types.actions
|
|||||||
|
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use BotAction objects realisations to notify user about bot actions
|
||||||
|
*/
|
||||||
@Serializable(BotActionSerializer::class)
|
@Serializable(BotActionSerializer::class)
|
||||||
sealed class BotAction {
|
sealed class BotAction {
|
||||||
abstract val actionName: String
|
abstract val actionName: String
|
||||||
@@ -31,54 +34,80 @@ internal object BotActionSerializer: KSerializer<BotAction> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use BotAction objects realisations to notify user about bot actions
|
* Will notify user that bot is "typing" something
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Serializable(BotActionSerializer::class)
|
@Serializable(BotActionSerializer::class)
|
||||||
object TypingAction : BotAction() {
|
object TypingAction : BotAction() {
|
||||||
override val actionName: String = "typing"
|
override val actionName: String = "typing"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will notify user that bot is uploading some photo
|
||||||
|
*/
|
||||||
@Serializable(BotActionSerializer::class)
|
@Serializable(BotActionSerializer::class)
|
||||||
object UploadPhotoAction : BotAction() {
|
object UploadPhotoAction : BotAction() {
|
||||||
override val actionName: String = "upload_photo"
|
override val actionName: String = "upload_photo"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will notify user that bot is recording some video
|
||||||
|
*/
|
||||||
@Serializable(BotActionSerializer::class)
|
@Serializable(BotActionSerializer::class)
|
||||||
object RecordVideoAction : BotAction() {
|
object RecordVideoAction : BotAction() {
|
||||||
override val actionName: String = "record_video"
|
override val actionName: String = "record_video"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will notify user that bot is uploading some photo
|
||||||
|
*/
|
||||||
@Serializable(BotActionSerializer::class)
|
@Serializable(BotActionSerializer::class)
|
||||||
object UploadVideoAction : BotAction() {
|
object UploadVideoAction : BotAction() {
|
||||||
override val actionName: String = "upload_video"
|
override val actionName: String = "upload_video"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will notify user that bot is recording some audio
|
||||||
|
*/
|
||||||
@Serializable(BotActionSerializer::class)
|
@Serializable(BotActionSerializer::class)
|
||||||
object RecordAudioAction : BotAction() {
|
object RecordAudioAction : BotAction() {
|
||||||
override val actionName: String = "record_audio"
|
override val actionName: String = "record_audio"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will notify user that bot is uploading some audio
|
||||||
|
*/
|
||||||
@Serializable(BotActionSerializer::class)
|
@Serializable(BotActionSerializer::class)
|
||||||
object UploadAudioAction : BotAction() {
|
object UploadAudioAction : BotAction() {
|
||||||
override val actionName: String = "upload_audio"
|
override val actionName: String = "upload_audio"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will notify user that bot is uploading some document
|
||||||
|
*/
|
||||||
@Serializable(BotActionSerializer::class)
|
@Serializable(BotActionSerializer::class)
|
||||||
object UploadDocumentAction : BotAction() {
|
object UploadDocumentAction : BotAction() {
|
||||||
override val actionName: String = "upload_document"
|
override val actionName: String = "upload_document"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will notify user that bot is trying to find location
|
||||||
|
*/
|
||||||
@Serializable(BotActionSerializer::class)
|
@Serializable(BotActionSerializer::class)
|
||||||
object FindLocationAction : BotAction() {
|
object FindLocationAction : BotAction() {
|
||||||
override val actionName: String = "find_location"
|
override val actionName: String = "find_location"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will notify user that bot is recording video note
|
||||||
|
*/
|
||||||
@Serializable(BotActionSerializer::class)
|
@Serializable(BotActionSerializer::class)
|
||||||
object RecordVideoNoteAction : BotAction() {
|
object RecordVideoNoteAction : BotAction() {
|
||||||
override val actionName: String = "record_video_note"
|
override val actionName: String = "record_video_note"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will notify user that bot is uploading video note
|
||||||
|
*/
|
||||||
@Serializable(BotActionSerializer::class)
|
@Serializable(BotActionSerializer::class)
|
||||||
object UploadVideoNoteAction : BotAction() {
|
object UploadVideoNoteAction : BotAction() {
|
||||||
override val actionName: String = "upload_video_note"
|
override val actionName: String = "upload_video_note"
|
||||||
|
|||||||
@@ -15,9 +15,15 @@ object DartsDiceAnimationType : DiceAnimationType() {
|
|||||||
override val emoji: String = "\uD83C\uDFAF"
|
override val emoji: String = "\uD83C\uDFAF"
|
||||||
}
|
}
|
||||||
@Serializable(DiceAnimationTypeSerializer::class)
|
@Serializable(DiceAnimationTypeSerializer::class)
|
||||||
class UnknownDiceAnimationType(
|
object BasketballDiceAnimationType : DiceAnimationType() {
|
||||||
|
override val emoji: String = "\uD83C\uDFC0"
|
||||||
|
}
|
||||||
|
@Serializable(DiceAnimationTypeSerializer::class)
|
||||||
|
data class CustomDiceAnimationType(
|
||||||
override val emoji: String
|
override val emoji: String
|
||||||
) : DiceAnimationType()
|
) : DiceAnimationType()
|
||||||
|
@Deprecated("Renamed", ReplaceWith("CustomDiceAnimationType"))
|
||||||
|
typealias UnknownDiceAnimationType = CustomDiceAnimationType
|
||||||
|
|
||||||
@Serializer(DiceAnimationType::class)
|
@Serializer(DiceAnimationType::class)
|
||||||
internal object DiceAnimationTypeSerializer : KSerializer<DiceAnimationType> {
|
internal object DiceAnimationTypeSerializer : KSerializer<DiceAnimationType> {
|
||||||
@@ -26,7 +32,8 @@ internal object DiceAnimationTypeSerializer : KSerializer<DiceAnimationType> {
|
|||||||
return when (val type = decoder.decodeString()) {
|
return when (val type = decoder.decodeString()) {
|
||||||
CubeDiceAnimationType.emoji -> CubeDiceAnimationType
|
CubeDiceAnimationType.emoji -> CubeDiceAnimationType
|
||||||
DartsDiceAnimationType.emoji -> DartsDiceAnimationType
|
DartsDiceAnimationType.emoji -> DartsDiceAnimationType
|
||||||
else -> UnknownDiceAnimationType(type)
|
BasketballDiceAnimationType.emoji -> BasketballDiceAnimationType
|
||||||
|
else -> CustomDiceAnimationType(type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.FileId
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.FileUniqueId
|
import com.github.insanusmokrassar.TelegramBotAPI.types.FileUniqueId
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.fileUniqueIdField
|
import com.github.insanusmokrassar.TelegramBotAPI.types.fileUniqueIdField
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.files.abstracts.*
|
import com.github.insanusmokrassar.TelegramBotAPI.types.files.abstracts.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.MimeType
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@ data class AnimationFile(
|
|||||||
@SerialName(fileNameField)
|
@SerialName(fileNameField)
|
||||||
override val fileName: String? = null,
|
override val fileName: String? = null,
|
||||||
@SerialName(mimeTypeField)
|
@SerialName(mimeTypeField)
|
||||||
override val mimeType: String? = null,
|
override val mimeType: MimeType? = null,
|
||||||
@SerialName(fileSizeField)
|
@SerialName(fileSizeField)
|
||||||
override val fileSize: Long? = null
|
override val fileSize: Long? = null
|
||||||
) : TelegramMediaFile, MimedMediaFile, ThumbedMediaFile, PlayableMediaFile, CustomNamedMediaFile, SizedMediaFile
|
) : TelegramMediaFile, MimedMediaFile, ThumbedMediaFile, PlayableMediaFile, CustomNamedMediaFile, SizedMediaFile
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.FileId
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.FileUniqueId
|
import com.github.insanusmokrassar.TelegramBotAPI.types.FileUniqueId
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.fileUniqueIdField
|
import com.github.insanusmokrassar.TelegramBotAPI.types.fileUniqueIdField
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.files.abstracts.*
|
import com.github.insanusmokrassar.TelegramBotAPI.types.files.abstracts.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.MimeType
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@@ -18,7 +19,7 @@ data class AudioFile(
|
|||||||
override val performer: String? = null,
|
override val performer: String? = null,
|
||||||
override val title: String? = null,
|
override val title: String? = null,
|
||||||
@SerialName(mimeTypeField)
|
@SerialName(mimeTypeField)
|
||||||
override val mimeType: String? = null,
|
override val mimeType: MimeType? = null,
|
||||||
@SerialName(fileSizeField)
|
@SerialName(fileSizeField)
|
||||||
override val fileSize: Long? = null,
|
override val fileSize: Long? = null,
|
||||||
override val thumb: PhotoSize? = null
|
override val thumb: PhotoSize? = null
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.FileId
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.FileUniqueId
|
import com.github.insanusmokrassar.TelegramBotAPI.types.FileUniqueId
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.fileUniqueIdField
|
import com.github.insanusmokrassar.TelegramBotAPI.types.fileUniqueIdField
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.files.abstracts.*
|
import com.github.insanusmokrassar.TelegramBotAPI.types.files.abstracts.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.MimeType
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@@ -17,7 +18,7 @@ data class DocumentFile(
|
|||||||
override val fileSize: Long? = null,
|
override val fileSize: Long? = null,
|
||||||
override val thumb: PhotoSize? = null,
|
override val thumb: PhotoSize? = null,
|
||||||
@SerialName(mimeTypeField)
|
@SerialName(mimeTypeField)
|
||||||
override val mimeType: String? = null,
|
override val mimeType: MimeType? = null,
|
||||||
@SerialName(fileNameField)
|
@SerialName(fileNameField)
|
||||||
override val fileName: String? = null
|
override val fileName: String? = null
|
||||||
) : TelegramMediaFile, MimedMediaFile, ThumbedMediaFile, CustomNamedMediaFile
|
) : TelegramMediaFile, MimedMediaFile, ThumbedMediaFile, CustomNamedMediaFile
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.FileId
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.FileUniqueId
|
import com.github.insanusmokrassar.TelegramBotAPI.types.FileUniqueId
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.fileUniqueIdField
|
import com.github.insanusmokrassar.TelegramBotAPI.types.fileUniqueIdField
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.files.abstracts.*
|
import com.github.insanusmokrassar.TelegramBotAPI.types.files.abstracts.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.MimeType
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@@ -18,7 +19,7 @@ data class VideoFile(
|
|||||||
override val duration: Long? = null,
|
override val duration: Long? = null,
|
||||||
override val thumb: PhotoSize? = null,
|
override val thumb: PhotoSize? = null,
|
||||||
@SerialName(mimeTypeField)
|
@SerialName(mimeTypeField)
|
||||||
override val mimeType: String? = null,
|
override val mimeType: MimeType? = null,
|
||||||
@SerialName(fileSizeField)
|
@SerialName(fileSizeField)
|
||||||
override val fileSize: Long? = null
|
override val fileSize: Long? = null
|
||||||
) : TelegramMediaFile, MimedMediaFile, ThumbedMediaFile, PlayableMediaFile, SizedMediaFile
|
) : TelegramMediaFile, MimedMediaFile, ThumbedMediaFile, PlayableMediaFile, SizedMediaFile
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package com.github.insanusmokrassar.TelegramBotAPI.types.files
|
package com.github.insanusmokrassar.TelegramBotAPI.types.files
|
||||||
|
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.FileId
|
import com.github.insanusmokrassar.TelegramBotAPI.requests.abstracts.FileId
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.FileUniqueId
|
import com.github.insanusmokrassar.TelegramBotAPI.types.*
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.fileUniqueIdField
|
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.files.abstracts.*
|
import com.github.insanusmokrassar.TelegramBotAPI.types.files.abstracts.*
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.utils.MimeType
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@@ -13,9 +13,10 @@ data class VoiceFile(
|
|||||||
override val fileId: FileId,
|
override val fileId: FileId,
|
||||||
@SerialName(fileUniqueIdField)
|
@SerialName(fileUniqueIdField)
|
||||||
override val fileUniqueId: FileUniqueId,
|
override val fileUniqueId: FileUniqueId,
|
||||||
|
@SerialName(durationField)
|
||||||
override val duration: Long? = null,
|
override val duration: Long? = null,
|
||||||
@SerialName(mimeTypeField)
|
@SerialName(mimeTypeField)
|
||||||
override val mimeType: String? = null,
|
override val mimeType: MimeType? = null,
|
||||||
@SerialName(fileSizeField)
|
@SerialName(fileSizeField)
|
||||||
override val fileSize: Long? = null
|
override val fileSize: Long? = null
|
||||||
) : TelegramMediaFile, MimedMediaFile, PlayableMediaFile
|
) : TelegramMediaFile, MimedMediaFile, PlayableMediaFile
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ internal const val fileSizeField = "file_size"
|
|||||||
internal const val filePathField = "file_path"
|
internal const val filePathField = "file_path"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Declare common part of media files in Telegram. Note: it is not representation of `File` type
|
* Declare common part of media files in Telegram. Note: it is not representation of JVM `File` type
|
||||||
*/
|
*/
|
||||||
interface TelegramMediaFile {
|
interface TelegramMediaFile {
|
||||||
val fileId: FileId
|
val fileId: FileId
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
package com.github.insanusmokrassar.TelegramBotAPI.types.message
|
package com.github.insanusmokrassar.TelegramBotAPI.types.message
|
||||||
|
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.AuthorSignature
|
import com.github.insanusmokrassar.TelegramBotAPI.types.*
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.MessageIdentifier
|
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
|
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.Chat
|
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.Chat
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.CommonMessage
|
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Message
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Message
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MessageContent
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MessageContent
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.PossiblySentViaBotCommonMessage
|
||||||
import com.soywiz.klock.DateTime
|
import com.soywiz.klock.DateTime
|
||||||
|
|
||||||
data class ChannelMessage<T: MessageContent>(
|
data class ChannelMessage<T: MessageContent>(
|
||||||
@@ -18,5 +17,6 @@ data class ChannelMessage<T: MessageContent>(
|
|||||||
override val forwardInfo: ForwardInfo?,
|
override val forwardInfo: ForwardInfo?,
|
||||||
override val replyTo: Message?,
|
override val replyTo: Message?,
|
||||||
override val replyMarkup: InlineKeyboardMarkup?,
|
override val replyMarkup: InlineKeyboardMarkup?,
|
||||||
|
override val senderBot: CommonBot?,
|
||||||
val authorSignature: AuthorSignature?
|
val authorSignature: AuthorSignature?
|
||||||
) : CommonMessage<T>
|
) : PossiblySentViaBotCommonMessage<T>
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
package com.github.insanusmokrassar.TelegramBotAPI.types.message
|
package com.github.insanusmokrassar.TelegramBotAPI.types.message
|
||||||
|
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.MessageIdentifier
|
import com.github.insanusmokrassar.TelegramBotAPI.types.*
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.User
|
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
|
import com.github.insanusmokrassar.TelegramBotAPI.types.buttons.InlineKeyboardMarkup
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.Chat
|
import com.github.insanusmokrassar.TelegramBotAPI.types.chat.abstracts.Chat
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.*
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.FromUserMessage
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts.Message
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MessageContent
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.MessageContent
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.content.abstracts.PossiblySentViaBotCommonMessage
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.message.payments.SuccessfulPaymentInfo
|
import com.github.insanusmokrassar.TelegramBotAPI.types.message.payments.SuccessfulPaymentInfo
|
||||||
import com.soywiz.klock.DateTime
|
import com.soywiz.klock.DateTime
|
||||||
|
|
||||||
@@ -19,5 +20,6 @@ data class CommonMessageImpl<T: MessageContent>(
|
|||||||
override val forwardInfo: ForwardInfo?,
|
override val forwardInfo: ForwardInfo?,
|
||||||
override val replyTo: Message?,
|
override val replyTo: Message?,
|
||||||
override val replyMarkup: InlineKeyboardMarkup?,
|
override val replyMarkup: InlineKeyboardMarkup?,
|
||||||
|
override val senderBot: CommonBot?,
|
||||||
val paymentInfo: SuccessfulPaymentInfo?
|
val paymentInfo: SuccessfulPaymentInfo?
|
||||||
) : Message, CommonMessage<T>, FromUserMessage
|
) : PossiblySentViaBotCommonMessage<T>, FromUserMessage
|
||||||
@@ -20,6 +20,7 @@ import com.github.insanusmokrassar.TelegramBotAPI.types.message.payments.Success
|
|||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.payments.Invoice
|
import com.github.insanusmokrassar.TelegramBotAPI.types.payments.Invoice
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.payments.SuccessfulPayment
|
import com.github.insanusmokrassar.TelegramBotAPI.types.payments.SuccessfulPayment
|
||||||
import com.github.insanusmokrassar.TelegramBotAPI.types.polls.Poll
|
import com.github.insanusmokrassar.TelegramBotAPI.types.polls.Poll
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.venue.Venue
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
@@ -42,6 +43,7 @@ internal data class RawMessage(
|
|||||||
private val forward_sender_name: ForwardSenderName? = null,
|
private val forward_sender_name: ForwardSenderName? = null,
|
||||||
private val forward_date: TelegramDate? = null,
|
private val forward_date: TelegramDate? = null,
|
||||||
private val reply_to_message: RawMessage? = null,
|
private val reply_to_message: RawMessage? = null,
|
||||||
|
private val via_bot: CommonBot? = null,
|
||||||
private val edit_date: TelegramDate? = null,
|
private val edit_date: TelegramDate? = null,
|
||||||
private val media_group_id: MediaGroupIdentifier? = null,
|
private val media_group_id: MediaGroupIdentifier? = null,
|
||||||
private val author_signature: AuthorSignature? = null,
|
private val author_signature: AuthorSignature? = null,
|
||||||
@@ -147,7 +149,7 @@ internal data class RawMessage(
|
|||||||
)
|
)
|
||||||
forward_from_chat is ChannelChat -> ForwardFromChannelInfo(
|
forward_from_chat is ChannelChat -> ForwardFromChannelInfo(
|
||||||
forward_date,
|
forward_date,
|
||||||
forward_from_message_id ?: throw IllegalStateException("Channel forwarded message must contain message id, but was not"),
|
forward_from_message_id ?: error("Channel forwarded message must contain message id, but was not"),
|
||||||
forward_from_chat,
|
forward_from_chat,
|
||||||
forward_signature
|
forward_signature
|
||||||
)
|
)
|
||||||
@@ -208,7 +210,7 @@ internal data class RawMessage(
|
|||||||
chatEvent as? ChannelEvent ?: throwWrongChatEvent(ChannelEvent::class, chatEvent),
|
chatEvent as? ChannelEvent ?: throwWrongChatEvent(ChannelEvent::class, chatEvent),
|
||||||
date.asDate
|
date.asDate
|
||||||
)
|
)
|
||||||
else -> throw IllegalStateException("Expected one of the public chats, but was $chat (in extracting of chat event message)")
|
else -> error("Expected one of the public chats, but was $chat (in extracting of chat event message)")
|
||||||
}
|
}
|
||||||
} ?: content?.let { content ->
|
} ?: content?.let { content ->
|
||||||
media_group_id?.let {
|
media_group_id?.let {
|
||||||
@@ -221,7 +223,7 @@ internal data class RawMessage(
|
|||||||
when (content) {
|
when (content) {
|
||||||
is PhotoContent -> content
|
is PhotoContent -> content
|
||||||
is VideoContent -> content
|
is VideoContent -> content
|
||||||
else -> throw IllegalStateException("Unsupported content for media group")
|
else -> error("Unsupported content for media group")
|
||||||
},
|
},
|
||||||
edit_date?.asDate,
|
edit_date?.asDate,
|
||||||
forwarded,
|
forwarded,
|
||||||
@@ -237,7 +239,7 @@ internal data class RawMessage(
|
|||||||
when (content) {
|
when (content) {
|
||||||
is PhotoContent -> content
|
is PhotoContent -> content
|
||||||
is VideoContent -> content
|
is VideoContent -> content
|
||||||
else -> throw IllegalStateException("Unsupported content for media group")
|
else -> error("Unsupported content for media group")
|
||||||
},
|
},
|
||||||
edit_date?.asDate,
|
edit_date?.asDate,
|
||||||
forwarded,
|
forwarded,
|
||||||
@@ -255,12 +257,12 @@ internal data class RawMessage(
|
|||||||
forwarded,
|
forwarded,
|
||||||
reply_to_message?.asMessage,
|
reply_to_message?.asMessage,
|
||||||
reply_markup,
|
reply_markup,
|
||||||
|
via_bot,
|
||||||
author_signature
|
author_signature
|
||||||
)
|
)
|
||||||
else -> CommonMessageImpl(
|
else -> CommonMessageImpl(
|
||||||
messageId,
|
messageId,
|
||||||
from
|
from ?: error("Was detected common message, but owner (sender) of the message was not found"),
|
||||||
?: throw IllegalStateException("Was detected common message, but owner (sender) of the message was not found"),
|
|
||||||
chat,
|
chat,
|
||||||
content,
|
content,
|
||||||
date.asDate,
|
date.asDate,
|
||||||
@@ -268,10 +270,11 @@ internal data class RawMessage(
|
|||||||
forwarded,
|
forwarded,
|
||||||
reply_to_message?.asMessage,
|
reply_to_message?.asMessage,
|
||||||
reply_markup,
|
reply_markup,
|
||||||
|
via_bot,
|
||||||
paymentInfo
|
paymentInfo
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} ?: throw IllegalStateException("Was not found supported type of data")
|
} ?: error("Was not found supported type of data")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
UnknownMessageType(
|
UnknownMessageType(
|
||||||
messageId,
|
messageId,
|
||||||
@@ -283,6 +286,6 @@ internal data class RawMessage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun throwWrongChatEvent(expected: KClass<*>, but: ChatEvent): CommonEvent {
|
private fun throwWrongChatEvent(expected: KClass<*>, but: ChatEvent): CommonEvent {
|
||||||
throw IllegalStateException("Wrong type of chat event: expected $expected, but was $but")
|
error("Wrong type of chat event: expected $expected, but was $but")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.types.message.abstracts
|
||||||
|
|
||||||
|
import com.github.insanusmokrassar.TelegramBotAPI.types.CommonBot
|
||||||
|
|
||||||
|
interface PossiblySentViaBot {
|
||||||
|
val senderBot: CommonBot?
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user