mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2025-11-26 17:25:46 +00:00
Compare commits
83 Commits
klassindex
...
0.35.9
| Author | SHA1 | Date | |
|---|---|---|---|
| 3e5d939ea5 | |||
| 24f91e4aee | |||
| fe169fafaf | |||
| aeb6fad409 | |||
| 94ad758814 | |||
| 5f01e26377 | |||
| f82ac0ce9d | |||
| c8491765e9 | |||
| 53a3e11836 | |||
| fcccbe3252 | |||
| 584bf06109 | |||
| ef0083079e | |||
| 0d01e9bc78 | |||
| 89aef3d77b | |||
| 24c47b00d4 | |||
| a046a72392 | |||
| a5a530c9bd | |||
| 9cf82a3564 | |||
| 46cc37be62 | |||
| 1fbaf396aa | |||
| 76985501f5 | |||
| 8d8bcfba01 | |||
| e0f3957249 | |||
| 3f1b018808 | |||
| 7af5ab17b7 | |||
| 0fec35f0dc | |||
| ee81f49a75 | |||
| 807952201b | |||
| 5d6ba0f59e | |||
| 3a61b522ab | |||
| 83304023a6 | |||
| f62e13aaca | |||
| ae1fb25336 | |||
| 4e3ea6cd80 | |||
| 148203eabf | |||
| 4465b573ca | |||
| f0dda60630 | |||
| 47135a1b65 | |||
| d8f830c60f | |||
| 226b8dee21 | |||
| a109771d20 | |||
| c028434f30 | |||
| d5c6ce32bb | |||
| d92cac5e07 | |||
| 9b21b5290c | |||
| 13ca63d27d | |||
| ad917dda1b | |||
| 7b1344e9c8 | |||
| c4fbd2f1c6 | |||
| c90bcea42c | |||
| e75c93d626 | |||
| 58dcbe8751 | |||
| 17806cde25 | |||
| f147a3d620 | |||
| 9eb6008a73 | |||
| f7d2c8bbd2 | |||
| f42cf78969 | |||
| 9a14932511 | |||
| 149ecf175b | |||
| 2049fea82a | |||
| 40d94cca70 | |||
| c8ad68ea69 | |||
| c66d64adbc | |||
| b475976ff1 | |||
| ea8db5b851 | |||
| af2fabf1ca | |||
| abc0457a36 | |||
| 8dbdbdee13 | |||
| 0c31379ff5 | |||
| 3b3cf81aaa | |||
| 1642075a75 | |||
| 760c9f2916 | |||
| 219238cf19 | |||
| 762087fc09 | |||
| 142fae1ede | |||
| 95abc72bf3 | |||
| 1d37a7446c | |||
| 7d35114b5d | |||
| 75f4226772 | |||
| 96d980cb8a | |||
| ed077ae1bc | |||
| 9540797ffc | |||
| 217b01994e |
87
CHANGELOG.md
87
CHANGELOG.md
@@ -1,5 +1,88 @@
|
||||
# TelegramBotAPI changelog
|
||||
|
||||
## 0.35.9
|
||||
|
||||
* `Common`:
|
||||
* `Version`:
|
||||
* `Kotlin`: `1.5.30` -> `1.5.31`
|
||||
* `Klock`: `2.4.1` -> `2.4.2`
|
||||
* `MicroUtils`: `0.5.25` -> `0.5.28`
|
||||
* `Core`:
|
||||
* New `BotAction` implementation - `CustomBotAction`
|
||||
* `LocationContent` has been divided to two different types: `LiveLocationContent` and `StaticLocationContent`
|
||||
* `API`:
|
||||
* Two new extensions: `TelegramBot#answer` with `CallbackQuery` and `InlineQuery`
|
||||
* `Behaviour Builder`:
|
||||
* All triggers have been changed to use two filters: filter for in subcontext data and filter for incoming data
|
||||
* New waiters for edited content
|
||||
* New extension `BehaviourContext#followLocation`
|
||||
* New factory-functions:
|
||||
* `BehaviourContextReceiver`
|
||||
* `BehaviourContextAndTypeReceiver`
|
||||
* `BehaviourContextAndTwoTypesReceiver`
|
||||
* Old API for triggers with the flags like `includeFilterByChatInBehaviourSubContext` have been deprecated
|
||||
|
||||
## 0.35.8
|
||||
|
||||
* `Common`:
|
||||
* `Version`:
|
||||
* `MicroUtils`: `0.5.24` -> `0.5.25`
|
||||
* `UUID`: `0.3.0` -> `0.3.1`
|
||||
* `Core`:
|
||||
* `MultipartRequestCallFactory` now will use file name as multipart `filename` parameter instead of generated file id
|
||||
* New extension `MPPFile#asMultipartFile`
|
||||
* `API`
|
||||
* Fixes in `TelegramBot#withAction`
|
||||
* `Behaviour Builder`:
|
||||
* New extensions `BehaviourContext#commandWithArgs` and `BehaviourContext#onCommandWithArgs`
|
||||
|
||||
## 0.35.7
|
||||
|
||||
* `Common`:
|
||||
* `Version`:
|
||||
* `Kotlin`: `1.5.21` -> `1.5.30`
|
||||
* `Klock`: `2.3.3` -> `2.4.1`
|
||||
* `Ktor`: `1.6.2` -> `1.6.3`
|
||||
* `Coroutines`: `1.5.1` -> `1.5.2`
|
||||
* `MicroUtils`: `0.5.21` -> `0.5.24`
|
||||
|
||||
## 0.35.6
|
||||
|
||||
* `Common`:
|
||||
* `Version`:
|
||||
* `Klock`: `2.3.1` -> `2.3.3`
|
||||
* `MicroUtils`: `0.5.19` -> `0.5.21`
|
||||
* `Core`:
|
||||
* All `FlowsUpdatesFilter` flows have been renamed and updated
|
||||
* `Utils`:
|
||||
* Extensions `allSentMessagesFlow` and `allSentMediaGroupsFlow` have been deprecated
|
||||
|
||||
## 0.35.5
|
||||
|
||||
**MIME TYPES FOR REQUESTS HAVE BEEN DEPRECATED DUE TO REDUNDANCY OF MIME TYPES IN FILES SENDING**
|
||||
|
||||
* `Core`:
|
||||
* Several new extensions `ByteReadChannel#asStorageFile` and `ByteReadChannelAllocator#asStorageFile`
|
||||
* Several new extensions `ByteArray#asMultipartFile`, `ByteReadChannel#asMultipartFile` and
|
||||
`ByteReadChannelAllocator#asMultipartFile`
|
||||
* New extension `StorageFile#asMultipartFile`
|
||||
* `API`:
|
||||
* New extensions `TelegramBot#downloadFile` for writing of incoming bytes to the file
|
||||
* New extensions `TelegramBot#downloadFileStream` and `TelegramBot#downloadFileStreamAllocator` for getting of input
|
||||
streams instead of whole bytes arrays
|
||||
* Old extensions `TelegramBot#downloadFile` has been replaced to the new package. Migration: replace in your project
|
||||
`import dev.inmo.tgbotapi.extensions.api.downloadFile` with `import dev.inmo.tgbotapi.extensions.api.files.downloadFile`
|
||||
* `PathedFile#filename` extension has been deprecated, and new property `PathedFile#fileName` has been included
|
||||
directly in `PathedFile`
|
||||
* `Utils`:
|
||||
* Add several functions `convertToStorageFile` and extensions `TelegramBot#convertToStorageFile`
|
||||
|
||||
## 0.35.4 Hotfix
|
||||
|
||||
* `Common`:
|
||||
* `Version`:
|
||||
* `MicroUtils`: `0.5.18` -> `0.5.19`
|
||||
|
||||
## 0.35.3
|
||||
|
||||
* `Common`:
|
||||
@@ -8,6 +91,8 @@
|
||||
* `Ktor`: `1.6.1` -> `1.6.2`
|
||||
* `MicroUtils`: `0.5.16` -> `0.5.18`
|
||||
* `Core`:
|
||||
* **`SimpleRequestCallFactory` and `MultipartRequestCallFactory` became a classes instead of objects to avoid
|
||||
collisions in different bots**
|
||||
* Support of strongly-typed ietf language codes has been added
|
||||
* `API`:
|
||||
* New extension `TelegramBot#downloadFile` for any `MediaContent`
|
||||
@@ -18,6 +103,8 @@
|
||||
* New `TelegramBot#buildBehaviour` extension with `FlowUpdatesFilter` and `CoroutineScope` with
|
||||
default `CoroutineScope`
|
||||
* New typealias `SimpleFilter` for unifying triggers filter signatures
|
||||
* All waiters got real filters (`SimpleFilter`) and rename old filters as mappers
|
||||
* New extensions for `Any`: `as`/`when`/`require` for `WithOptionalLanguageCode` and `WithLanguageCode`
|
||||
|
||||
## 0.35.2
|
||||
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
# TelegramBotAPI
|
||||
|
||||
- [TelegramBotAPI](#telegrambotapi)
|
||||
* [Examples](#examples)
|
||||
+ [Most common example](#most-common-example)
|
||||
+ [Handling only last messages](#handling-only-last-messages)
|
||||
+ [Build a little bit more complex behaviour](#build-a-little-bit-more-complex-behaviour)
|
||||
+ [More examples](#more-examples)
|
||||
|
||||
<small><i><a href='http://ecotrust-canada.github.io/markdown-toc/'>Table of contents generated with markdown-toc</a></i></small>
|
||||
|
||||
Hello! This is a set of libraries for working with Telegram Bot API.
|
||||
|
||||
| Common info | [](https://github.com/KotlinBy/awesome-kotlin) [](https://github.com/InsanusMokrassar/TelegramBotAPI/actions) [Small survey](https://forms.gle/2Hex2ynbHWHhi1KY7)|
|
||||
|
||||
1
TelegramBotAPI.drawio
Normal file
1
TelegramBotAPI.drawio
Normal file
File diff suppressed because one or more lines are too long
@@ -1,311 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<minder version="1.11.3">
|
||||
<theme name="default" label="Default" index="-1"/>
|
||||
<styles>
|
||||
<style level="0" isset="true" branchmargin="100" 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" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/>
|
||||
<style level="1" isset="true" branchmargin="100" 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" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/>
|
||||
<style level="2" isset="true" branchmargin="100" 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" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/>
|
||||
<style level="3" isset="true" branchmargin="100" 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" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/>
|
||||
<style level="4" isset="true" branchmargin="100" 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" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/>
|
||||
<style level="5" isset="true" branchmargin="100" 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" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/>
|
||||
<style level="6" isset="true" branchmargin="100" 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" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/>
|
||||
<style level="7" isset="true" branchmargin="100" 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" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/>
|
||||
<style level="8" isset="true" branchmargin="100" 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" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/>
|
||||
<style level="9" isset="true" branchmargin="100" 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" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/>
|
||||
<style level="10" isset="true" branchmargin="100" 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" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/>
|
||||
</styles>
|
||||
<drawarea x="-950.47548925255796" y="-49.650554065281653" scale="0.5"/>
|
||||
<images/>
|
||||
<nodes>
|
||||
<node id="0" posx="1378.798161778599" posy="159.04571601189673" width="472" height="168" side="top" fold="false" treesize="743" layout="Downwards" group="false">
|
||||
<style branchmargin="100" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="439" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true"/>
|
||||
<nodename posx="1394.798161778599" posy="175.04571601189673" maxwidth="488.96484375">
|
||||
<text data="tgbotapi.core Root project with API. It is not recommended to use its requests directly and better to use at least tgbotapi.extensions.api"/>
|
||||
</nodename>
|
||||
<nodenote></nodenote>
|
||||
<nodes>
|
||||
<node id="1" posx="1411.798161778599" posy="427.04571601189673" width="406" height="145" side="bottom" fold="false" treesize="743" color="#68b723" colorroot="true" layout="Downwards" group="false">
|
||||
<style branchmargin="100" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="none" nodewidth="394" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true"/>
|
||||
<nodename posx="1427.798161778599" posy="443.04571601189673" maxwidth="419.451171875">
|
||||
<text data="TelegramBotAPI extensions Family of projects which are fully based on TelegramBotAPI and extend its functionality"/>
|
||||
</nodename>
|
||||
<nodenote></nodenote>
|
||||
<nodes>
|
||||
<node id="2" posx="1247.298161778599" posy="672.04571601189673" width="296" height="191" side="bottom" fold="false" treesize="296" color="#68b723" colorroot="true" layout="Downwards" group="false">
|
||||
<style branchmargin="100" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="203" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true"/>
|
||||
<nodename posx="1263.298161778599" posy="688.04571601189673" maxwidth="295.90315755208337">
|
||||
<text data="tgbotapi.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="3" posx="1609.298161778599" posy="672.04571601189673" width="307" height="168" side="bottom" fold="false" treesize="439" color="#68b723" colorroot="true" layout="Downwards" group="false">
|
||||
<style branchmargin="100" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="286" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true"/>
|
||||
<nodename posx="1625.298161778599" posy="688.04571601189673" maxwidth="299.252197265625">
|
||||
<text data="tgbotapi.extensions.utils Extensions project with utils things which will make easier different operations"/>
|
||||
</nodename>
|
||||
<nodenote></nodenote>
|
||||
<nodes>
|
||||
<node id="4" posx="1543.298161778599" posy="940.04571601189673" width="439" height="122" side="bottom" fold="false" treesize="439" color="#68b723" colorroot="false" layout="Downwards" group="false">
|
||||
<style branchmargin="100" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="387" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true"/>
|
||||
<nodename posx="1559.298161778599" posy="956.04571601189673" maxwidth="408.97932942708348">
|
||||
<text data="tgbotapi.extensions.behaviour_builder Extension project for building bot behaviour via special dsl"/>
|
||||
</nodename>
|
||||
<nodenote></nodenote>
|
||||
</node>
|
||||
</nodes>
|
||||
</node>
|
||||
</nodes>
|
||||
</node>
|
||||
</nodes>
|
||||
</node>
|
||||
<node id="5" posx="1391.8445078072455" posy="1155.6062730594231" width="461" height="236" side="bottom" fold="false" treesize="461" layout="Downwards" group="false">
|
||||
<style branchmargin="100" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="430" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true"/>
|
||||
<nodename posx="1407.8445078072455" posy="1171.6062730594231" maxwidth="453.885498046875">
|
||||
<text data="tgbotapi Here included all available TelegramBotAPI libraries: * tgbotapi.core * tgbotapi.extensions.api * tgbotapi.extensions.utils * tgbotapi.extensions.behaviour_builder">
|
||||
<color>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="67" end="68" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="84" end="85" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="111" end="112" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
<range start="139" end="140" extra="rgb(255,0,0)"/>
|
||||
</color>
|
||||
</text>
|
||||
</nodename>
|
||||
<nodenote></nodenote>
|
||||
</node>
|
||||
</nodes>
|
||||
<groups/>
|
||||
<connections>
|
||||
<connection from_id="2" to_id="5" drag_x="1475.8213347929195" drag_y="1014.8259945356604" color="#777777">
|
||||
<style connectiondash="dotted" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/>
|
||||
<title></title>
|
||||
<note></note>
|
||||
</connection>
|
||||
<connection from_id="4" to_id="5" drag_x="1691.5447998046875" drag_y="1107.00439453125" color="#777777">
|
||||
<style connectiondash="dotted" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/>
|
||||
<title></title>
|
||||
<note></note>
|
||||
</connection>
|
||||
<connection from_id="3" to_id="5" drag_x="1483.48876953125" drag_y="896.18115234375">
|
||||
<style connectiondash="dotted" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/>
|
||||
<title></title>
|
||||
<note></note>
|
||||
</connection>
|
||||
</connections>
|
||||
<stickers/>
|
||||
</minder>
|
||||
12
build.gradle
12
build.gradle
@@ -18,14 +18,12 @@ plugins {
|
||||
id "org.jetbrains.kotlin.plugin.serialization" version "$kotlin_version" apply false
|
||||
}
|
||||
|
||||
// temporal crutch until legacy tests will be stabled or legacy target will be removed
|
||||
allprojects {
|
||||
repositories {
|
||||
maven { url 'https://jitpack.io' }
|
||||
if (it != rootProject.findProject("docs")) {
|
||||
tasks.whenTaskAdded { task ->
|
||||
if (task.name == "jsLegacyBrowserTest" || task.name == "jsLegacyNodeTest") {
|
||||
task.enabled = false
|
||||
}
|
||||
if (it != rootProject.findProject("docs")) {
|
||||
tasks.whenTaskAdded { task ->
|
||||
if(task.name == "jsLegacyBrowserTest" || task.name == "jsLegacyNodeTest") {
|
||||
task.enabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,17 +77,17 @@ Object callback = {
|
||||
}
|
||||
}
|
||||
|
||||
// named("commonMain") {
|
||||
// sourceRoots.setFrom(findSourcesWithName("commonMain"))
|
||||
// }
|
||||
//
|
||||
// named("jsMain") {
|
||||
// sourceRoots.setFrom(findSourcesWithName("jsMain"))
|
||||
// }
|
||||
//
|
||||
// named("jvmMain") {
|
||||
// sourceRoots.setFrom(findSourcesWithName("jvmMain"))
|
||||
// }
|
||||
named("commonMain") {
|
||||
sourceRoots.setFrom(findSourcesWithName("commonMain"))
|
||||
}
|
||||
|
||||
named("jsMain") {
|
||||
sourceRoots.setFrom(findSourcesWithName("jsMain"))
|
||||
}
|
||||
|
||||
named("jvmMain") {
|
||||
sourceRoots.setFrom(findSourcesWithName("jvmMain"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
dokka_version=1.4.32
|
||||
dokka_version=1.5.30
|
||||
|
||||
org.gradle.jvmargs=-Xmx1024m
|
||||
|
||||
@@ -5,18 +5,18 @@ kotlin.js.generate.externals=true
|
||||
kotlin.incremental=true
|
||||
kotlin.incremental.js=true
|
||||
|
||||
kotlin_version=1.5.21
|
||||
kotlin_coroutines_version=1.5.1
|
||||
kotlin_version=1.5.31
|
||||
kotlin_coroutines_version=1.5.2
|
||||
kotlin_serialisation_runtime_version=1.2.2
|
||||
klock_version=2.3.1
|
||||
uuid_version=0.3.0
|
||||
ktor_version=1.6.2
|
||||
klock_version=2.4.2
|
||||
uuid_version=0.3.1
|
||||
ktor_version=1.6.3
|
||||
|
||||
micro_utils_version=0.5.18
|
||||
micro_utils_version=0.5.28
|
||||
|
||||
javax_activation_version=1.1.1
|
||||
|
||||
library_group=dev.inmo
|
||||
library_version=0.35.3
|
||||
library_version=0.35.9
|
||||
|
||||
github_release_plugin_version=2.2.12
|
||||
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 9.0 KiB |
@@ -2,6 +2,20 @@
|
||||
|
||||
[](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.core)
|
||||
|
||||
- [TelegramBotAPI Core](#telegrambotapi-core)
|
||||
* [What is it?](#what-is-it-)
|
||||
* [Compatibility](#compatibility)
|
||||
* [How to implement library?](#how-to-implement-library-)
|
||||
+ [Maven](#maven)
|
||||
+ [Gradle](#gradle)
|
||||
* [How to work with library?](#how-to-work-with-library-)
|
||||
+ [Types](#types)
|
||||
+ [Requests](#requests)
|
||||
+ [RequestsExecutor](#requestsexecutor)
|
||||
+ [Passport](#passport)
|
||||
|
||||
<small><i><a href='http://ecotrust-canada.github.io/markdown-toc/'>Table of contents generated with markdown-toc</a></i></small>
|
||||
|
||||
## What is it?
|
||||
|
||||
Library for Object-Oriented and type-safe work with Telegram Bot API. Most part of some specific solves or unuseful
|
||||
|
||||
@@ -3,7 +3,6 @@ buildscript {
|
||||
mavenLocal()
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url "https://plugins.gradle.org/m2/" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -15,7 +14,6 @@ buildscript {
|
||||
plugins {
|
||||
id "org.jetbrains.kotlin.multiplatform"
|
||||
id "org.jetbrains.kotlin.plugin.serialization"
|
||||
id "org.jetbrains.kotlin.kapt"
|
||||
}
|
||||
|
||||
project.version = "$library_version"
|
||||
@@ -56,7 +54,6 @@ kotlin {
|
||||
api "dev.inmo:micro_utils.language_codes:$micro_utils_version"
|
||||
|
||||
api "io.ktor:ktor-client-core:$ktor_version"
|
||||
api "com.github.matfax.klassindex:library:4.+"
|
||||
}
|
||||
}
|
||||
commonTest {
|
||||
@@ -98,35 +95,3 @@ kotlin {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
kapt "com.github.matfax.klassindex:processor:4.+"
|
||||
}
|
||||
|
||||
kapt {
|
||||
useBuildCache = false
|
||||
arguments {
|
||||
arg(
|
||||
"com.github.matfax.klassindex.IndexSubclasses",
|
||||
// "dev.inmo.tgbotapi.types.update.abstracts.Update",
|
||||
// "dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.ChatEvent",
|
||||
// "dev.inmo.tgbotapi.types.passport.decrypted.abstracts.SecureValue",
|
||||
// "dev.inmo.tgbotapi.types.message.content.abstracts.ResendableContent",
|
||||
"dev.inmo.tgbotapi.CommonAbstracts.WithOptionalLanguageCode",
|
||||
// "dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts.EncryptedPassportElement",
|
||||
// "dev.inmo.tgbotapi.types.passport.PassportElementError",
|
||||
// "dev.inmo.tgbotapi.types.CallbackQuery.CallbackQuery",
|
||||
// "dev.inmo.tgbotapi.types.buttons.KeyboardMarkup",
|
||||
// "dev.inmo.tgbotapi.types.actions.BotAction",
|
||||
// "dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.InlineKeyboardButton",
|
||||
// "dev.inmo.tgbotapi.types.ChatMember.abstracts.ChatMember",
|
||||
// "dev.inmo.tgbotapi.types.files.abstracts.TelegramMediaFile",
|
||||
// "dev.inmo.tgbotapi.types.InlineQueries.abstracts.InlineQuery",
|
||||
// "dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.InlineQueryResult",
|
||||
// "dev.inmo.tgbotapi.types.InlineQueries.abstracts.InputMessageContent",
|
||||
// "dev.inmo.tgbotapi.types.InputMedia.InputMedia",
|
||||
// "dev.inmo.tgbotapi.types.polls.Poll",
|
||||
// "dev.inmo.tgbotapi.types.update.abstracts.Update"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
package dev.inmo.tgbotapi.CommonAbstracts
|
||||
|
||||
import dev.inmo.micro_utils.language_codes.IetfLanguageCode
|
||||
|
||||
interface WithOptionalLanguageCode {
|
||||
val ietfLanguageCode: IetfLanguageCode?
|
||||
|
||||
val languageCode: String?
|
||||
get() = ietfLanguageCode ?.code
|
||||
}
|
||||
|
||||
interface WithLanguageCode : WithOptionalLanguageCode {
|
||||
override val ietfLanguageCode: IetfLanguageCode
|
||||
|
||||
override val languageCode: String
|
||||
get() = ietfLanguageCode.code
|
||||
}
|
||||
@@ -42,6 +42,14 @@ inline fun telegramBot(
|
||||
crossinline builder: KtorRequestsExecutorBuilder.() -> Unit = {}
|
||||
): TelegramBot = telegramBot(TelegramAPIUrlsKeeper(token, apiUrl), builder)
|
||||
|
||||
@RiskFeature
|
||||
fun createTelegramBotDefaultKtorCallRequestsFactories() = listOf(
|
||||
SimpleRequestCallFactory(),
|
||||
MultipartRequestCallFactory(),
|
||||
DownloadFileRequestCallFactory,
|
||||
DownloadFileChannelRequestCallFactory
|
||||
)
|
||||
|
||||
class KtorRequestsExecutor(
|
||||
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper,
|
||||
client: HttpClient = HttpClient(),
|
||||
@@ -52,7 +60,7 @@ class KtorRequestsExecutor(
|
||||
) : BaseRequestsExecutor(telegramAPIUrlsKeeper) {
|
||||
private val callsFactories: List<KtorCallFactory> = callsFactories.run {
|
||||
if (!excludeDefaultFactories) {
|
||||
this + listOf(SimpleRequestCallFactory, MultipartRequestCallFactory, DownloadFileRequestCallFactory)
|
||||
this + createTelegramBotDefaultKtorCallRequestsFactories()
|
||||
} else {
|
||||
this
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package dev.inmo.tgbotapi.bot.Ktor.base
|
||||
|
||||
import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions
|
||||
import dev.inmo.tgbotapi.bot.Ktor.KtorCallFactory
|
||||
import dev.inmo.tgbotapi.requests.DownloadFileStream
|
||||
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||
import dev.inmo.tgbotapi.utils.ByteReadChannelAllocator
|
||||
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.call.receive
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.statement.HttpStatement
|
||||
import io.ktor.utils.io.*
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlin.coroutines.coroutineContext
|
||||
|
||||
object DownloadFileChannelRequestCallFactory : KtorCallFactory {
|
||||
override suspend fun <T : Any> makeCall(
|
||||
client: HttpClient,
|
||||
urlsKeeper: TelegramAPIUrlsKeeper,
|
||||
request: Request<T>,
|
||||
jsonFormatter: Json
|
||||
): T? = (request as? DownloadFileStream) ?.let {
|
||||
val fullUrl = urlsKeeper.createFileLinkUrl(it.filePath)
|
||||
|
||||
ByteReadChannelAllocator {
|
||||
val scope = CoroutineScope(coroutineContext)
|
||||
val outChannel = ByteChannel()
|
||||
scope.launchSafelyWithoutExceptions {
|
||||
client.get<HttpStatement>(fullUrl).execute { httpResponse ->
|
||||
val channel: ByteReadChannel = httpResponse.receive()
|
||||
channel.copyAndClose(outChannel)
|
||||
}
|
||||
}
|
||||
outChannel
|
||||
} as T
|
||||
}
|
||||
}
|
||||
@@ -16,9 +16,9 @@ object DownloadFileRequestCallFactory : KtorCallFactory {
|
||||
request: Request<T>,
|
||||
jsonFormatter: Json
|
||||
): T? = (request as? DownloadFile) ?.let {
|
||||
val fullUrl = "${urlsKeeper.fileBaseUrl}/${it.filePath}"
|
||||
val fullUrl = urlsKeeper.createFileLinkUrl(it.filePath)
|
||||
|
||||
return safely {
|
||||
safely {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
client.get<ByteArray>(fullUrl) as T // always ByteArray
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package dev.inmo.tgbotapi.bot.Ktor.base
|
||||
|
||||
import dev.inmo.tgbotapi.bot.Ktor.KtorCallFactory
|
||||
import dev.inmo.tgbotapi.requests.abstracts.*
|
||||
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
|
||||
import dev.inmo.tgbotapi.utils.mapWithCommonValues
|
||||
@@ -9,7 +10,7 @@ import io.ktor.client.request.forms.formData
|
||||
import io.ktor.http.Headers
|
||||
import io.ktor.http.HttpHeaders
|
||||
|
||||
object MultipartRequestCallFactory : AbstractRequestCallFactory() {
|
||||
class MultipartRequestCallFactory : AbstractRequestCallFactory() {
|
||||
override fun <T : Any> prepareCallBody(
|
||||
client: HttpClient,
|
||||
urlsKeeper: TelegramAPIUrlsKeeper,
|
||||
@@ -23,8 +24,7 @@ object MultipartRequestCallFactory : AbstractRequestCallFactory() {
|
||||
is MultipartFile -> appendInput(
|
||||
key,
|
||||
Headers.build {
|
||||
append(HttpHeaders.ContentType, value.mimeType)
|
||||
append(HttpHeaders.ContentDisposition, "filename=${value.fileId}")
|
||||
append(HttpHeaders.ContentDisposition, "filename=${value.filename}")
|
||||
},
|
||||
block = value.file::input
|
||||
)
|
||||
@@ -35,4 +35,7 @@ object MultipartRequestCallFactory : AbstractRequestCallFactory() {
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("Use class MultipartRequestCallFactory() constructor call instead of just MultipartRequestCallFactory")
|
||||
companion object : KtorCallFactory by MultipartRequestCallFactory()
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package dev.inmo.tgbotapi.bot.Ktor.base
|
||||
|
||||
import dev.inmo.tgbotapi.bot.Ktor.KtorCallFactory
|
||||
import dev.inmo.tgbotapi.requests.abstracts.*
|
||||
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.content.TextContent
|
||||
|
||||
object SimpleRequestCallFactory : AbstractRequestCallFactory() {
|
||||
class SimpleRequestCallFactory : AbstractRequestCallFactory() {
|
||||
override fun <T : Any> prepareCallBody(
|
||||
client: HttpClient,
|
||||
urlsKeeper: TelegramAPIUrlsKeeper,
|
||||
@@ -19,4 +20,7 @@ object SimpleRequestCallFactory : AbstractRequestCallFactory() {
|
||||
ContentType.Application.Json
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("Use class SimpleRequestCallFactory() constructor call instead of just SimpleRequestCallFactory")
|
||||
companion object : KtorCallFactory by SimpleRequestCallFactory()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.inmo.tgbotapi.requests
|
||||
|
||||
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||
import dev.inmo.tgbotapi.utils.ByteReadChannelAllocator
|
||||
import dev.inmo.tgbotapi.utils.ByteReadChannelAllocatorDeserializationStrategy
|
||||
import kotlinx.serialization.DeserializationStrategy
|
||||
|
||||
class DownloadFileStream(
|
||||
val filePath: String
|
||||
) : Request<ByteReadChannelAllocator> {
|
||||
override fun method(): String = filePath
|
||||
override val resultDeserializer: DeserializationStrategy<ByteReadChannelAllocator>
|
||||
get() = ByteReadChannelAllocatorDeserializationStrategy
|
||||
|
||||
}
|
||||
@@ -1,13 +1,26 @@
|
||||
package dev.inmo.tgbotapi.requests.abstracts
|
||||
|
||||
import dev.inmo.tgbotapi.utils.RiskFeature
|
||||
import dev.inmo.tgbotapi.utils.StorageFile
|
||||
import dev.inmo.micro_utils.common.MPPFile
|
||||
import dev.inmo.tgbotapi.utils.*
|
||||
import io.ktor.utils.io.ByteReadChannel
|
||||
import io.ktor.utils.io.core.Input
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.descriptors.*
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
|
||||
/**
|
||||
* Common type for all files in Telegram Bot API which can be sent via requests like [dev.inmo.tgbotapi.requests.send.media.SendDocument].
|
||||
* You may use methods like [MPPFile.asMultipartFile] when you want to send files from your file system, but you should
|
||||
* remember about [restrictions][https://core.telegram.org/bots/api#sending-files] in Telegram for bots. In case you
|
||||
* wish to send file by its url, use [FileId] and pass your url as [FileId.fileId]
|
||||
*
|
||||
* @see MPPFile.asMultipartFile
|
||||
* @see ByteArray.asMultipartFile
|
||||
* @see ByteReadChannel.asMultipartFile
|
||||
* @see ByteReadChannelAllocator.asMultipartFile
|
||||
*/
|
||||
@Serializable(InputFileSerializer::class)
|
||||
sealed class InputFile {
|
||||
abstract val fileId: String
|
||||
@@ -42,12 +55,38 @@ object InputFileSerializer : KSerializer<InputFile> {
|
||||
// TODO:: add checks for files size
|
||||
/**
|
||||
* Contains info about file for sending
|
||||
*
|
||||
* @see asMultipartFile
|
||||
*/
|
||||
@Serializable(InputFileSerializer::class)
|
||||
data class MultipartFile (
|
||||
val file: StorageFile,
|
||||
val mimeType: String = file.storageFileInfo.contentType,
|
||||
val filename: String = file.storageFileInfo.fileName
|
||||
) : InputFile() {
|
||||
override val fileId: String = file.storageFileInfo.generateCustomName()
|
||||
|
||||
@Deprecated("This constructor is redundant. Use constructor without mime type")
|
||||
constructor(file: StorageFile, mimeType: String, filename: String): this(file, filename)
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE", "unused")
|
||||
inline fun StorageFile.asMultipartFile() = MultipartFile(this)
|
||||
|
||||
@Deprecated("This method is redundant. Use asMultipartFile without mime type")
|
||||
@Suppress("NOTHING_TO_INLINE", "unused")
|
||||
inline fun ByteArray.asMultipartFile(
|
||||
fileName: String,
|
||||
mimeType: MimeType
|
||||
) = MultipartFile(asStorageFile(fileName))
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE", "unused")
|
||||
suspend inline fun ByteReadChannel.asMultipartFile(
|
||||
fileName: String
|
||||
) = MultipartFile(asStorageFile(fileName))
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE", "unused")
|
||||
suspend inline fun ByteReadChannelAllocator.asMultipartFile(
|
||||
fileName: String
|
||||
) = this.invoke().asMultipartFile(fileName)
|
||||
|
||||
expect suspend fun MPPFile.asMultipartFile(): MultipartFile
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package dev.inmo.tgbotapi.requests.bot
|
||||
|
||||
import dev.inmo.tgbotapi.CommonAbstracts.WithOptionalLanguageCode
|
||||
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
|
||||
import dev.inmo.tgbotapi.types.abstracts.WithOptionalLanguageCode
|
||||
import dev.inmo.tgbotapi.types.commands.BotCommandScope
|
||||
|
||||
sealed interface MyCommandsRequest<T : Any> : SimpleRequest<T>, WithOptionalLanguageCode {
|
||||
|
||||
@@ -2,8 +2,9 @@ package dev.inmo.tgbotapi.requests.bot
|
||||
|
||||
import dev.inmo.micro_utils.language_codes.IetfLanguageCode
|
||||
import dev.inmo.micro_utils.language_codes.IetfLanguageCodeSerializer
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.commands.*
|
||||
import dev.inmo.tgbotapi.types.languageCodeField
|
||||
import dev.inmo.tgbotapi.types.scopeField
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@ import dev.inmo.tgbotapi.requests.edit.media.MediaContentMessageResultDeserializ
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.*
|
||||
|
||||
const val editMessageCaptionMethod = "editMessageCaption"
|
||||
|
||||
@@ -4,10 +4,10 @@ import dev.inmo.tgbotapi.requests.edit.abstracts.*
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.*
|
||||
|
||||
fun EditInlineMessageCaption(
|
||||
|
||||
@@ -5,12 +5,12 @@ import dev.inmo.tgbotapi.requests.send.TextContentMessageResultDeserializer
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||
import dev.inmo.tgbotapi.types.message.content.TextContent
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.*
|
||||
|
||||
const val editMessageTextMethod = "editMessageText"
|
||||
|
||||
@@ -4,10 +4,10 @@ import dev.inmo.tgbotapi.requests.edit.abstracts.*
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.*
|
||||
|
||||
fun EditInlineMessageText(
|
||||
|
||||
@@ -7,10 +7,10 @@ import dev.inmo.tgbotapi.requests.send.abstracts.ReplyingMarkupSendMessageReques
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSource
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.*
|
||||
|
||||
fun CopyMessage(
|
||||
|
||||
@@ -6,7 +6,7 @@ import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
||||
import dev.inmo.tgbotapi.types.message.content.LocationContent
|
||||
import dev.inmo.tgbotapi.types.message.content.*
|
||||
import dev.inmo.tgbotapi.utils.throwRangeError
|
||||
import kotlinx.serialization.*
|
||||
|
||||
|
||||
@@ -5,13 +5,13 @@ import dev.inmo.tgbotapi.requests.send.abstracts.*
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
||||
import dev.inmo.tgbotapi.types.message.content.TextContent
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.utils.throwRangeError
|
||||
import kotlinx.serialization.*
|
||||
|
||||
|
||||
@@ -6,13 +6,13 @@ import dev.inmo.tgbotapi.requests.send.media.base.*
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
||||
import dev.inmo.tgbotapi.types.message.content.media.AnimationContent
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.utils.mapOfNotNull
|
||||
import dev.inmo.tgbotapi.utils.throwRangeError
|
||||
import kotlinx.serialization.*
|
||||
|
||||
@@ -7,13 +7,13 @@ import dev.inmo.tgbotapi.requests.send.media.base.*
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSource
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
||||
import dev.inmo.tgbotapi.types.message.content.media.AudioContent
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.utils.mapOfNotNull
|
||||
import dev.inmo.tgbotapi.utils.throwRangeError
|
||||
import kotlinx.serialization.*
|
||||
|
||||
@@ -6,13 +6,13 @@ import dev.inmo.tgbotapi.requests.send.media.base.*
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
||||
import dev.inmo.tgbotapi.types.message.content.media.DocumentContent
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.utils.mapOfNotNull
|
||||
import dev.inmo.tgbotapi.utils.throwRangeError
|
||||
import kotlinx.serialization.*
|
||||
|
||||
@@ -6,13 +6,13 @@ import dev.inmo.tgbotapi.requests.send.media.base.*
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
||||
import dev.inmo.tgbotapi.types.message.content.media.PhotoContent
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.utils.throwRangeError
|
||||
import kotlinx.serialization.*
|
||||
|
||||
|
||||
@@ -6,13 +6,13 @@ import dev.inmo.tgbotapi.requests.send.media.base.*
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
||||
import dev.inmo.tgbotapi.types.message.content.media.VideoContent
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.utils.mapOfNotNull
|
||||
import dev.inmo.tgbotapi.utils.throwRangeError
|
||||
import kotlinx.serialization.*
|
||||
|
||||
@@ -6,13 +6,13 @@ import dev.inmo.tgbotapi.requests.send.media.base.*
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
||||
import dev.inmo.tgbotapi.types.message.content.media.VoiceContent
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.utils.mapOfNotNull
|
||||
import dev.inmo.tgbotapi.utils.throwRangeError
|
||||
import kotlinx.serialization.*
|
||||
|
||||
@@ -7,13 +7,13 @@ import dev.inmo.tgbotapi.requests.send.abstracts.SendMessageRequest
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSource
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
|
||||
import dev.inmo.tgbotapi.types.message.content.PollContent
|
||||
import dev.inmo.tgbotapi.types.polls.*
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.*
|
||||
|
||||
private val commonResultDeserializer: DeserializationStrategy<ContentMessage<PollContent>> = TelegramBotAPIMessageDeserializationStrategyClass()
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package dev.inmo.tgbotapi.types.InlineQueries.ChosenInlineResult
|
||||
|
||||
import dev.inmo.tgbotapi.CommonAbstracts.FromUser
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.InlineMessageIdentifier
|
||||
import dev.inmo.tgbotapi.types.InlineQueryIdentifier
|
||||
|
||||
sealed interface ChosenInlineResult : FromUser {
|
||||
val resultId: InlineQueryIdentifier //chosen temporary, can be changed
|
||||
|
||||
@@ -7,10 +7,10 @@ import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results
|
||||
import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputMessageContent
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
||||
@@ -6,10 +6,10 @@ import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results
|
||||
import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputMessageContent
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results
|
||||
import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputMessageContent
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
||||
@@ -6,12 +6,12 @@ import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results
|
||||
import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputMessageContent
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
||||
import dev.inmo.tgbotapi.types.files.abstracts.mimeTypeField
|
||||
import dev.inmo.tgbotapi.utils.MimeType
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results
|
||||
import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputMessageContent
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
||||
@@ -6,11 +6,11 @@ import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results
|
||||
import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputMessageContent
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
||||
import dev.inmo.tgbotapi.utils.MimeType
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results
|
||||
import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputMessageContent
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
||||
@@ -6,11 +6,11 @@ import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results
|
||||
import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputMessageContent
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
||||
import dev.inmo.tgbotapi.utils.MimeType
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results
|
||||
import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputMessageContent
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
||||
@@ -6,10 +6,10 @@ import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results
|
||||
import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputMessageContent
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results
|
||||
import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputMessageContent
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
||||
@@ -6,12 +6,12 @@ import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results
|
||||
import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputMessageContent
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSource
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
||||
import dev.inmo.tgbotapi.types.files.abstracts.mimeTypeField
|
||||
import dev.inmo.tgbotapi.utils.MimeType
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results
|
||||
import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputMessageContent
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
||||
@@ -6,10 +6,10 @@ import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results
|
||||
import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputMessageContent
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@ import dev.inmo.tgbotapi.CommonAbstracts.types.DisableWebPagePreview
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@ import dev.inmo.tgbotapi.requests.abstracts.fileIdToSend
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
||||
@@ -6,10 +6,10 @@ import dev.inmo.tgbotapi.requests.abstracts.fileIdToSend
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.files.AudioFile
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.*
|
||||
|
||||
internal const val audioInputMediaType = "audio"
|
||||
|
||||
@@ -4,10 +4,10 @@ import dev.inmo.tgbotapi.requests.abstracts.*
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.files.DocumentFile
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.*
|
||||
|
||||
internal const val documentInputMediaType = "document"
|
||||
|
||||
@@ -5,10 +5,10 @@ import dev.inmo.tgbotapi.requests.abstracts.fileIdToSend
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.types.files.PhotoSize
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.*
|
||||
|
||||
internal const val photoInputMediaType = "photo"
|
||||
|
||||
@@ -5,9 +5,9 @@ import dev.inmo.tgbotapi.requests.abstracts.fileIdToSend
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.*
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
|
||||
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
|
||||
import dev.inmo.tgbotapi.utils.extensions.makeString
|
||||
import kotlinx.serialization.*
|
||||
|
||||
internal const val videoInputMediaType = "video"
|
||||
|
||||
@@ -2,7 +2,7 @@ package dev.inmo.tgbotapi.types
|
||||
|
||||
import dev.inmo.micro_utils.language_codes.IetfLanguageCode
|
||||
import dev.inmo.micro_utils.language_codes.IetfLanguageCodeSerializer
|
||||
import dev.inmo.tgbotapi.CommonAbstracts.WithOptionalLanguageCode
|
||||
import dev.inmo.tgbotapi.types.abstracts.WithOptionalLanguageCode
|
||||
import dev.inmo.tgbotapi.types.chat.abstracts.PrivateChat
|
||||
import dev.inmo.tgbotapi.types.chat.extended.ExtendedPrivateChatImpl
|
||||
import dev.inmo.tgbotapi.utils.*
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package dev.inmo.tgbotapi.types.abstracts
|
||||
|
||||
import dev.inmo.micro_utils.language_codes.IetfLanguageCode
|
||||
|
||||
interface WithOptionalLanguageCode {
|
||||
val ietfLanguageCode: IetfLanguageCode?
|
||||
|
||||
val languageCode: String?
|
||||
get() = ietfLanguageCode ?.code
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package dev.inmo.tgbotapi.types.actions
|
||||
|
||||
import dev.inmo.micro_utils.common.Warning
|
||||
import dev.inmo.tgbotapi.utils.RiskFeature
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
@@ -34,7 +36,7 @@ object BotActionSerializer: KSerializer<BotAction> {
|
||||
FindLocationAction.actionName -> FindLocationAction
|
||||
RecordVideoNoteAction.actionName -> RecordVideoNoteAction
|
||||
UploadVideoNoteAction.actionName -> UploadVideoNoteAction
|
||||
else -> throw IllegalStateException("Unknown action type: $actionName")
|
||||
else -> CustomBotAction(actionName)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -148,3 +150,9 @@ object UploadVideoNoteAction : BotAction {
|
||||
inline val uploadVideoNote
|
||||
get() = UploadVideoNoteAction
|
||||
inline fun BotAction.asUploadVideoNote() = this as? UploadVideoNoteAction
|
||||
|
||||
@Serializable(BotActionSerializer::class)
|
||||
@Warning("Use this action only in case you are pretty sure that there are no other action for your needs")
|
||||
class CustomBotAction @RiskFeature("Usage of this action may lead to errors") constructor(
|
||||
override val actionName: String
|
||||
) : BotAction
|
||||
|
||||
@@ -5,8 +5,7 @@ import dev.inmo.tgbotapi.types.FileUniqueId
|
||||
import dev.inmo.tgbotapi.types.fileUniqueIdField
|
||||
import dev.inmo.tgbotapi.types.files.abstracts.*
|
||||
import dev.inmo.tgbotapi.utils.*
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.*
|
||||
|
||||
@Serializable
|
||||
data class PathedFile(
|
||||
@@ -18,8 +17,14 @@ data class PathedFile(
|
||||
val filePath: String,
|
||||
@SerialName(fileSizeField)
|
||||
override val fileSize: Long? = null
|
||||
): TelegramMediaFile
|
||||
): TelegramMediaFile {
|
||||
@Transient
|
||||
val fileName: FileName by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
filePath.filenameFromUrl
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("Use fileName property instead", ReplaceWith("fileName"))
|
||||
val PathedFile.filename: FileName
|
||||
get() = filePath.filenameFromUrl
|
||||
fun TelegramAPIUrlsKeeper.resolveFileURL(file: PathedFile): String = "$fileBaseUrl/${file.filePath}"
|
||||
|
||||
@@ -10,6 +10,13 @@ import kotlinx.serialization.encoding.Encoder
|
||||
import kotlinx.serialization.json.JsonNull
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
|
||||
/**
|
||||
* Common interface for any known telegram location. Use [LocationSerializer] in case you wish
|
||||
* to serialize/deserialize [Location]
|
||||
*
|
||||
* @see dev.inmo.tgbotapi.extensions.utils.asStaticLocation
|
||||
* @see dev.inmo.tgbotapi.extensions.utils.asLiveLocation
|
||||
*/
|
||||
@Serializable(LocationSerializer::class)
|
||||
sealed interface Location : Locationed, HorizontallyAccured
|
||||
|
||||
|
||||
@@ -3,46 +3,143 @@ package dev.inmo.tgbotapi.types.message.content
|
||||
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||
import dev.inmo.tgbotapi.requests.send.SendLiveLocation
|
||||
import dev.inmo.tgbotapi.requests.send.SendStaticLocation
|
||||
import dev.inmo.tgbotapi.requests.send.abstracts.SendMessageRequest
|
||||
import dev.inmo.tgbotapi.types.ChatIdentifier
|
||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
||||
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
|
||||
import dev.inmo.tgbotapi.types.location.*
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||
import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
|
||||
import kotlinx.serialization.encoding.*
|
||||
|
||||
@Serializable
|
||||
data class LocationContent(
|
||||
/**
|
||||
* [MessageContent] with [location]. This interface contains [copy] method for cases when you do not want to use some
|
||||
* class casts for copying of content
|
||||
*
|
||||
* @see LocationContentSerializer
|
||||
* @see Location
|
||||
*/
|
||||
@Serializable(LocationContentSerializer::class)
|
||||
sealed interface LocationContent : MessageContent {
|
||||
val location: Location
|
||||
) : MessageContent {
|
||||
|
||||
fun copy(location: Location = this.location) {
|
||||
when (this) {
|
||||
is LiveLocationContent -> LiveLocationContent(
|
||||
(location as? LiveLocation) ?: this.location.copy(
|
||||
longitude = location.longitude,
|
||||
latitude = location.latitude,
|
||||
horizontalAccuracy = location.horizontalAccuracy
|
||||
)
|
||||
)
|
||||
is StaticLocationContent -> StaticLocationContent(
|
||||
(location as? StaticLocation) ?: this.location.copy(
|
||||
longitude = location.longitude,
|
||||
latitude = location.latitude,
|
||||
horizontalAccuracy = location.horizontalAccuracy
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
operator fun invoke(location: Location): LocationContent {
|
||||
return when (location) {
|
||||
is StaticLocation -> StaticLocationContent(location)
|
||||
is LiveLocation -> LiveLocationContent(location)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [KSerializer] for [LocationContent]
|
||||
*/
|
||||
@Serializer(LocationContent::class)
|
||||
object LocationContentSerializer : KSerializer<LocationContent> {
|
||||
override val descriptor: SerialDescriptor = buildClassSerialDescriptor("LocationContent") {
|
||||
element(LocationContent::location.name, LocationSerializer.descriptor)
|
||||
}
|
||||
|
||||
override fun deserialize(decoder: Decoder): LocationContent {
|
||||
lateinit var location: Location
|
||||
|
||||
decoder.decodeStructure(descriptor) {
|
||||
while (true) {
|
||||
when (val index = decodeElementIndex(descriptor)) {
|
||||
0 -> location = decodeSerializableElement(descriptor, index, LocationSerializer)
|
||||
CompositeDecoder.DECODE_DONE -> break
|
||||
else -> error("Unexpected index: $index")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return LocationContent(location)
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: LocationContent) {
|
||||
encoder.beginStructure(descriptor).apply {
|
||||
encodeSerializableElement(descriptor, 0, LocationSerializer, value.location)
|
||||
}.endStructure(descriptor)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* [LocationContent] which represents content with [LiveLocation]. In case you are tracking this content throw message
|
||||
* changes, may evolve to [StaticLocationContent]
|
||||
*
|
||||
* @see dev.inmo.tgbotapi.extensions.behaviour_builder.utils.followLocation
|
||||
*/
|
||||
@Serializable(LocationContentSerializer::class)
|
||||
data class LiveLocationContent(
|
||||
override val location: LiveLocation
|
||||
) : LocationContent {
|
||||
override fun createResend(
|
||||
chatId: ChatIdentifier,
|
||||
disableNotification: Boolean,
|
||||
replyToMessageId: MessageIdentifier?,
|
||||
allowSendingWithoutReply: Boolean?,
|
||||
replyMarkup: KeyboardMarkup?
|
||||
): Request<ContentMessage<LocationContent>> = when (location) {
|
||||
is StaticLocation -> SendStaticLocation(
|
||||
chatId,
|
||||
location.latitude,
|
||||
location.longitude,
|
||||
disableNotification,
|
||||
replyToMessageId,
|
||||
allowSendingWithoutReply,
|
||||
replyMarkup
|
||||
)
|
||||
is LiveLocation -> SendLiveLocation(
|
||||
chatId,
|
||||
location.latitude,
|
||||
location.longitude,
|
||||
location.livePeriod,
|
||||
location.horizontalAccuracy,
|
||||
location.heading,
|
||||
location.proximityAlertRadius,
|
||||
disableNotification,
|
||||
replyToMessageId,
|
||||
allowSendingWithoutReply,
|
||||
replyMarkup
|
||||
)
|
||||
}
|
||||
}
|
||||
): Request<ContentMessage<LiveLocationContent>> = SendLiveLocation(
|
||||
chatId,
|
||||
location.latitude,
|
||||
location.longitude,
|
||||
location.livePeriod,
|
||||
location.horizontalAccuracy,
|
||||
location.heading,
|
||||
location.proximityAlertRadius,
|
||||
disableNotification,
|
||||
replyToMessageId,
|
||||
allowSendingWithoutReply,
|
||||
replyMarkup
|
||||
) as SendMessageRequest<ContentMessage<LiveLocationContent>>
|
||||
}
|
||||
|
||||
/**
|
||||
* Just a [LocationContent] with [StaticLocation] [location]. It could be [LiveLocationContent] in previous time in case
|
||||
* when somebody has sent [LiveLocation] in chat and then stop to broadcast location
|
||||
*/
|
||||
@Serializable(LocationContentSerializer::class)
|
||||
data class StaticLocationContent(
|
||||
override val location: StaticLocation
|
||||
) : LocationContent {
|
||||
override fun createResend(
|
||||
chatId: ChatIdentifier,
|
||||
disableNotification: Boolean,
|
||||
replyToMessageId: MessageIdentifier?,
|
||||
allowSendingWithoutReply: Boolean?,
|
||||
replyMarkup: KeyboardMarkup?
|
||||
): Request<ContentMessage<StaticLocationContent>> = SendStaticLocation(
|
||||
chatId,
|
||||
location.latitude,
|
||||
location.longitude,
|
||||
disableNotification,
|
||||
replyToMessageId,
|
||||
allowSendingWithoutReply,
|
||||
replyMarkup
|
||||
) as SendMessageRequest<ContentMessage<StaticLocationContent>>
|
||||
}
|
||||
|
||||
@@ -14,24 +14,79 @@ interface FlowsUpdatesFilter : UpdatesFilter {
|
||||
val allUpdatesFlow: Flow<Update>
|
||||
val allUpdatesWithoutMediaGroupsGroupingFlow: Flow<Update>
|
||||
|
||||
val messagesFlow: Flow<MessageUpdate>
|
||||
val messageMediaGroupsFlow: Flow<MessageMediaGroupUpdate>
|
||||
val editedMessagesFlow: Flow<EditMessageUpdate>
|
||||
val editedMessageMediaGroupsFlow: Flow<EditMessageMediaGroupUpdate>
|
||||
val channelPostsFlow: Flow<ChannelPostUpdate>
|
||||
val channelPostMediaGroupsFlow: Flow<ChannelPostMediaGroupUpdate>
|
||||
val editedChannelPostsFlow: Flow<EditChannelPostUpdate>
|
||||
val editedChannelPostMediaGroupsFlow: Flow<EditChannelPostMediaGroupUpdate>
|
||||
val chosenInlineResultsFlow: Flow<ChosenInlineResultUpdate>
|
||||
val inlineQueriesFlow: Flow<InlineQueryUpdate>
|
||||
val callbackQueriesFlow: Flow<CallbackQueryUpdate>
|
||||
val shippingQueriesFlow: Flow<ShippingQueryUpdate>
|
||||
val preCheckoutQueriesFlow: Flow<PreCheckoutQueryUpdate>
|
||||
val pollsFlow: Flow<PollUpdate>
|
||||
val pollAnswersFlow: Flow<PollAnswerUpdate>
|
||||
val chatMemberUpdatesFlow: Flow<CommonChatMemberUpdatedUpdate>
|
||||
val myChatMemberUpdatesFlow: Flow<MyChatMemberUpdatedUpdate>
|
||||
val unknownUpdatesFlow: Flow<UnknownUpdate>
|
||||
|
||||
@Deprecated("Renamed", ReplaceWith("messagesFlow"))
|
||||
val messageFlow: Flow<MessageUpdate>
|
||||
get() = messagesFlow
|
||||
@Deprecated("Renamed", ReplaceWith("messageMediaGroupsFlow"))
|
||||
val messageMediaGroupFlow: Flow<MessageMediaGroupUpdate>
|
||||
get() = messageMediaGroupsFlow
|
||||
@Deprecated("Renamed", ReplaceWith("editedMessagesFlow"))
|
||||
val editedMessageFlow: Flow<EditMessageUpdate>
|
||||
get() = editedMessagesFlow
|
||||
@Deprecated("Renamed", ReplaceWith("editedMessageMediaGroupsFlow"))
|
||||
val editedMessageMediaGroupFlow: Flow<EditMessageMediaGroupUpdate>
|
||||
get() = editedMessageMediaGroupsFlow
|
||||
@Deprecated("Renamed", ReplaceWith("channelPostsFlow"))
|
||||
val channelPostFlow: Flow<ChannelPostUpdate>
|
||||
get() = channelPostsFlow
|
||||
@Deprecated("Renamed", ReplaceWith("channelPostMediaGroupsFlow"))
|
||||
val channelPostMediaGroupFlow: Flow<ChannelPostMediaGroupUpdate>
|
||||
get() = channelPostMediaGroupsFlow
|
||||
@Deprecated("Renamed", ReplaceWith("editedChannelPostsFlow"))
|
||||
val editedChannelPostFlow: Flow<EditChannelPostUpdate>
|
||||
get() = editedChannelPostsFlow
|
||||
@Deprecated("Renamed", ReplaceWith("editedChannelPostMediaGroupsFlow"))
|
||||
val editedChannelPostMediaGroupFlow: Flow<EditChannelPostMediaGroupUpdate>
|
||||
get() = editedChannelPostMediaGroupsFlow
|
||||
@Deprecated("Renamed", ReplaceWith("chosenInlineResultsFlow"))
|
||||
val chosenInlineResultFlow: Flow<ChosenInlineResultUpdate>
|
||||
get() = chosenInlineResultsFlow
|
||||
@Deprecated("Renamed", ReplaceWith("inlineQueriesFlow"))
|
||||
val inlineQueryFlow: Flow<InlineQueryUpdate>
|
||||
get() = inlineQueriesFlow
|
||||
@Deprecated("Renamed", ReplaceWith("callbackQueriesFlow"))
|
||||
val callbackQueryFlow: Flow<CallbackQueryUpdate>
|
||||
get() = callbackQueriesFlow
|
||||
@Deprecated("Renamed", ReplaceWith("shippingQueriesFlow"))
|
||||
val shippingQueryFlow: Flow<ShippingQueryUpdate>
|
||||
get() = shippingQueriesFlow
|
||||
@Deprecated("Renamed", ReplaceWith("preCheckoutQueriesFlow"))
|
||||
val preCheckoutQueryFlow: Flow<PreCheckoutQueryUpdate>
|
||||
get() = preCheckoutQueriesFlow
|
||||
@Deprecated("Renamed", ReplaceWith("pollsFlow"))
|
||||
val pollFlow: Flow<PollUpdate>
|
||||
get() = pollsFlow
|
||||
@Deprecated("Renamed", ReplaceWith("pollAnswersFlow"))
|
||||
val pollAnswerFlow: Flow<PollAnswerUpdate>
|
||||
get() = pollAnswersFlow
|
||||
@Deprecated("Renamed", ReplaceWith("chatMemberUpdatesFlow"))
|
||||
val chatMemberUpdatedFlow: Flow<CommonChatMemberUpdatedUpdate>
|
||||
get() = chatMemberUpdatesFlow
|
||||
@Deprecated("Renamed", ReplaceWith("myChatMemberUpdatesFlow"))
|
||||
val myChatMemberUpdatedFlow: Flow<MyChatMemberUpdatedUpdate>
|
||||
get() = myChatMemberUpdatesFlow
|
||||
@Deprecated("Renamed", ReplaceWith("unknownUpdatesFlow"))
|
||||
val unknownUpdateTypeFlow: Flow<UnknownUpdate>
|
||||
get() = unknownUpdatesFlow
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,22 +118,22 @@ class DefaultFlowsUpdatesFilter(
|
||||
updatesSharedFlow.emit(it)
|
||||
}
|
||||
|
||||
override val messageFlow: Flow<MessageUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val messageMediaGroupFlow: Flow<MessageMediaGroupUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val editedMessageFlow: Flow<EditMessageUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val editedMessageMediaGroupFlow: Flow<EditMessageMediaGroupUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val channelPostFlow: Flow<ChannelPostUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val channelPostMediaGroupFlow: Flow<ChannelPostMediaGroupUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val editedChannelPostFlow: Flow<EditChannelPostUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val editedChannelPostMediaGroupFlow: Flow<EditChannelPostMediaGroupUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val chosenInlineResultFlow: Flow<ChosenInlineResultUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val inlineQueryFlow: Flow<InlineQueryUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val callbackQueryFlow: Flow<CallbackQueryUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val shippingQueryFlow: Flow<ShippingQueryUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val preCheckoutQueryFlow: Flow<PreCheckoutQueryUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val pollFlow: Flow<PollUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val pollAnswerFlow: Flow<PollAnswerUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val chatMemberUpdatedFlow: Flow<CommonChatMemberUpdatedUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val myChatMemberUpdatedFlow: Flow<MyChatMemberUpdatedUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val unknownUpdateTypeFlow: Flow<UnknownUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val messagesFlow: Flow<MessageUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val messageMediaGroupsFlow: Flow<MessageMediaGroupUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val editedMessagesFlow: Flow<EditMessageUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val editedMessageMediaGroupsFlow: Flow<EditMessageMediaGroupUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val channelPostsFlow: Flow<ChannelPostUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val channelPostMediaGroupsFlow: Flow<ChannelPostMediaGroupUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val editedChannelPostsFlow: Flow<EditChannelPostUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val editedChannelPostMediaGroupsFlow: Flow<EditChannelPostMediaGroupUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val chosenInlineResultsFlow: Flow<ChosenInlineResultUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val inlineQueriesFlow: Flow<InlineQueryUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val callbackQueriesFlow: Flow<CallbackQueryUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val shippingQueriesFlow: Flow<ShippingQueryUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val preCheckoutQueriesFlow: Flow<PreCheckoutQueryUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val pollsFlow: Flow<PollUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val pollAnswersFlow: Flow<PollAnswerUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val chatMemberUpdatesFlow: Flow<CommonChatMemberUpdatedUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val myChatMemberUpdatesFlow: Flow<MyChatMemberUpdatedUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
override val unknownUpdatesFlow: Flow<UnknownUpdate> = allUpdatesFlow.filterIsInstance()
|
||||
}
|
||||
|
||||
@@ -12,9 +12,7 @@ package dev.inmo.tgbotapi.utils
|
||||
AnnotationTarget.PROPERTY_GETTER,
|
||||
AnnotationTarget.PROPERTY_SETTER,
|
||||
AnnotationTarget.FUNCTION,
|
||||
AnnotationTarget.TYPE,
|
||||
AnnotationTarget.TYPEALIAS,
|
||||
AnnotationTarget.TYPE_PARAMETER
|
||||
AnnotationTarget.TYPEALIAS
|
||||
)
|
||||
annotation class PreviewFeature
|
||||
|
||||
@@ -31,8 +29,6 @@ const val lowLevelRiskFeatureMessage = "This method is low-level and not recomme
|
||||
AnnotationTarget.PROPERTY_GETTER,
|
||||
AnnotationTarget.PROPERTY_SETTER,
|
||||
AnnotationTarget.FUNCTION,
|
||||
AnnotationTarget.TYPE,
|
||||
AnnotationTarget.TYPEALIAS,
|
||||
AnnotationTarget.TYPE_PARAMETER
|
||||
AnnotationTarget.TYPEALIAS
|
||||
)
|
||||
annotation class RiskFeature(val message: String = lowLevelRiskFeatureMessage)
|
||||
|
||||
@@ -8,4 +8,11 @@ object BuiltinMimeTypes {
|
||||
object Video {
|
||||
val MP4 = buildMimeType("video/mp4")
|
||||
}
|
||||
object Text {
|
||||
val Html = buildMimeType("text/html")
|
||||
}
|
||||
object Application {
|
||||
val Zip = buildMimeType("application/zip")
|
||||
val Pdf = buildMimeType("application/pdf")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package dev.inmo.tgbotapi.utils
|
||||
|
||||
import dev.inmo.micro_utils.common.ByteArrayAllocatorSerializer
|
||||
import io.ktor.utils.io.ByteReadChannel
|
||||
import kotlinx.serialization.DeserializationStrategy
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
|
||||
fun interface ByteReadChannelAllocator {
|
||||
suspend operator fun invoke(): ByteReadChannel
|
||||
}
|
||||
|
||||
object ByteReadChannelAllocatorDeserializationStrategy : DeserializationStrategy<ByteReadChannelAllocator> {
|
||||
override val descriptor: SerialDescriptor = ByteArrayAllocatorSerializer.descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): ByteReadChannelAllocator {
|
||||
val byteArrayAllocator = ByteArrayAllocatorSerializer.deserialize(decoder)
|
||||
return ByteReadChannelAllocator { ByteReadChannel(byteArrayAllocator()) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package dev.inmo.tgbotapi.utils
|
||||
|
||||
import io.ktor.utils.io.ByteReadChannel
|
||||
import io.ktor.utils.io.core.Input
|
||||
|
||||
expect suspend fun ByteReadChannel.asInput(): Input
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.inmo.tgbotapi.utils
|
||||
|
||||
import com.benasher44.uuid.uuid4
|
||||
import io.ktor.utils.io.*
|
||||
import io.ktor.utils.io.core.ByteReadPacket
|
||||
import io.ktor.utils.io.core.Input
|
||||
import kotlinx.serialization.Serializable
|
||||
@@ -13,9 +14,14 @@ import kotlinx.serialization.Serializable
|
||||
*/
|
||||
@Serializable
|
||||
data class StorageFileInfo(
|
||||
val contentType: String,
|
||||
val fileName: String
|
||||
) {
|
||||
@Deprecated("This constructor is redundant. Use constructor without mime type")
|
||||
constructor(
|
||||
contentType: String,
|
||||
fileName: String
|
||||
): this(fileName)
|
||||
|
||||
/**
|
||||
* This methods is required for random generation of name for keeping warranties about unique file name
|
||||
*/
|
||||
@@ -39,19 +45,55 @@ data class StorageFile(
|
||||
get() = inputSource()
|
||||
}
|
||||
|
||||
@Deprecated("This constructor is redundant. Use constructor without mime type")
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun StorageFile(
|
||||
fileName: String,
|
||||
bytes: ByteArray,
|
||||
mimeType: MimeType
|
||||
) = StorageFile(
|
||||
StorageFileInfo(mimeType.raw, fileName)
|
||||
StorageFileInfo(fileName)
|
||||
) {
|
||||
ByteReadPacket(bytes)
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun StorageFile(
|
||||
fileName: String,
|
||||
bytes: ByteArray
|
||||
) = StorageFile(
|
||||
StorageFileInfo(fileName)
|
||||
) {
|
||||
ByteReadPacket(bytes)
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
suspend inline fun StorageFile(
|
||||
fileName: String,
|
||||
byteReadChannel: ByteReadChannel
|
||||
) = StorageFile(
|
||||
StorageFileInfo(fileName),
|
||||
byteReadChannel.asInput().let { { it } }
|
||||
)
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE", "unused")
|
||||
inline fun ByteArray.asStorageFile(fileName: String, mimeType: MimeType) = StorageFile(fileName, this, mimeType)
|
||||
inline fun ByteArray.asStorageFile(
|
||||
fileName: String
|
||||
) = StorageFile(fileName, this)
|
||||
|
||||
@Deprecated("This constructor is redundant. Use constructor without mime type")
|
||||
@Suppress("NOTHING_TO_INLINE", "unused")
|
||||
inline fun ByteArray.asStorageFile(
|
||||
fileName: String,
|
||||
mimeType: MimeType
|
||||
) = asStorageFile(fileName)
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE", "unused")
|
||||
suspend inline fun ByteReadChannel.asStorageFile(
|
||||
fileName: String
|
||||
) = StorageFile(fileName, this)
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE", "unused")
|
||||
suspend inline fun ByteReadChannelAllocator.asStorageFile(
|
||||
fileName: String
|
||||
) = this.invoke().asStorageFile(fileName)
|
||||
|
||||
@@ -26,4 +26,6 @@ class TelegramAPIUrlsKeeper(
|
||||
commonAPIUrl = "$correctedHost/bot$token"
|
||||
fileBaseUrl = "$correctedHost/file/bot$token"
|
||||
}
|
||||
|
||||
fun createFileLinkUrl(filePath: String) = "${fileBaseUrl}/$filePath"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package dev.inmo.tgbotapi.utils.internal
|
||||
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.MultilevelTextSource
|
||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
|
||||
import dev.inmo.tgbotapi.types.UserId
|
||||
import dev.inmo.tgbotapi.types.link
|
||||
import dev.inmo.tgbotapi.utils.extensions.*
|
||||
|
||||
@@ -27,6 +27,7 @@ class BotActionTests {
|
||||
FindLocationAction -> example.botAction.actionName
|
||||
RecordVideoNoteAction -> example.botAction.actionName
|
||||
UploadVideoNoteAction -> example.botAction.actionName
|
||||
is CustomBotAction -> example.botAction.actionName
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package dev.inmo.tgbotapi.requests.abstracts
|
||||
|
||||
import dev.inmo.micro_utils.common.*
|
||||
import io.ktor.utils.io.ByteReadChannel
|
||||
|
||||
actual suspend fun MPPFile.asMultipartFile(): MultipartFile = ByteReadChannel(bytes()).asMultipartFile(
|
||||
filename.name
|
||||
)
|
||||
@@ -0,0 +1,8 @@
|
||||
package dev.inmo.tgbotapi.utils
|
||||
|
||||
import io.ktor.util.toByteArray
|
||||
import io.ktor.utils.io.ByteReadChannel
|
||||
import io.ktor.utils.io.core.ByteReadPacket
|
||||
import io.ktor.utils.io.core.Input
|
||||
|
||||
actual suspend fun ByteReadChannel.asInput(): Input = ByteReadPacket(toByteArray())
|
||||
@@ -0,0 +1,5 @@
|
||||
package dev.inmo.tgbotapi.requests.abstracts
|
||||
|
||||
import dev.inmo.micro_utils.common.MPPFile
|
||||
|
||||
actual suspend fun MPPFile.asMultipartFile(): MultipartFile = toInputFile()
|
||||
@@ -1,8 +1,8 @@
|
||||
package dev.inmo.tgbotapi.types
|
||||
|
||||
import dev.inmo.micro_utils.language_codes.IetfLanguageCode
|
||||
import dev.inmo.tgbotapi.CommonAbstracts.WithLanguageCode
|
||||
import dev.inmo.tgbotapi.types.abstracts.WithOptionalLanguageCode
|
||||
import java.util.*
|
||||
|
||||
fun IetfLanguageCode?.javaLocale() = this ?.code ?.let { Locale.forLanguageTag(it) }
|
||||
fun WithLanguageCode?.javaLocale() = this ?.ietfLanguageCode.javaLocale()
|
||||
fun WithOptionalLanguageCode?.javaLocale() = this ?.ietfLanguageCode ?.javaLocale()
|
||||
|
||||
@@ -7,10 +7,7 @@ import java.nio.file.Files
|
||||
fun StorageFile(
|
||||
file: File
|
||||
) = StorageFile(
|
||||
StorageFileInfo(
|
||||
Files.probeContentType(file.toPath()),
|
||||
file.name
|
||||
)
|
||||
StorageFileInfo(file.name)
|
||||
) {
|
||||
file.inputStream().asInput()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package dev.inmo.tgbotapi.utils
|
||||
|
||||
import io.ktor.utils.io.ByteReadChannel
|
||||
import io.ktor.utils.io.core.Input
|
||||
import io.ktor.utils.io.jvm.javaio.toInputStream
|
||||
import io.ktor.utils.io.streams.asInput
|
||||
import kotlinx.coroutines.job
|
||||
import kotlin.coroutines.coroutineContext
|
||||
|
||||
actual suspend fun ByteReadChannel.asInput(): Input = toInputStream(coroutineContext.job).asInput()
|
||||
@@ -1,69 +0,0 @@
|
||||
import com.github.matfax.klassindex.KlassIndex
|
||||
import dev.inmo.tgbotapi.types.CallbackQuery.CallbackQuery
|
||||
import dev.inmo.tgbotapi.types.ChatMember.abstracts.ChatMember
|
||||
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.InlineQueryResult
|
||||
import dev.inmo.tgbotapi.types.InlineQueries.abstracts.InlineQuery
|
||||
import dev.inmo.tgbotapi.types.InlineQueries.abstracts.InputMessageContent
|
||||
import dev.inmo.tgbotapi.types.InputMedia.InputMedia
|
||||
import dev.inmo.tgbotapi.types.actions.BotAction
|
||||
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.InlineKeyboardButton
|
||||
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
|
||||
import dev.inmo.tgbotapi.types.chat.abstracts.Chat
|
||||
import dev.inmo.tgbotapi.types.dice.DiceAnimationType
|
||||
import dev.inmo.tgbotapi.types.files.abstracts.TelegramMediaFile
|
||||
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.ChatEvent
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.Message
|
||||
import dev.inmo.tgbotapi.types.message.content.abstracts.ResendableContent
|
||||
import dev.inmo.tgbotapi.types.passport.PassportElementError
|
||||
import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.SecureValue
|
||||
import dev.inmo.tgbotapi.types.polls.Poll
|
||||
import dev.inmo.tgbotapi.types.update.abstracts.Update
|
||||
import dev.inmo.tgbotapi.utils.PreviewFeature
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
fun printlnInstanceSubclassesFuns(kclass: KClass<*>) {
|
||||
KlassIndex.getSubclasses(Message::class).forEach { subclass ->
|
||||
println("inline fun ${kclass.simpleName}.as${subclass.simpleName}(): ${subclass.simpleName}? = this as? ${subclass.simpleName}")
|
||||
}
|
||||
}
|
||||
|
||||
fun printlnInstancesSubclassesFuns(kclass: KClass<*>, subclasses: Set<KClass<*>>): List<Pair<String, String>> {
|
||||
return subclasses.map { subclass ->
|
||||
val typeUpperBounds = subclass.typeParameters.map { it.upperBounds.first() }
|
||||
val imports = "import ${subclass.qualifiedName}" + if (typeUpperBounds.isEmpty()) "" else typeUpperBounds.joinToString("\nimport ", "\nimport ")
|
||||
val subtype = "${subclass.simpleName}${if (typeUpperBounds.isEmpty()) "" else "<${typeUpperBounds.joinToString() { (it.classifier as KClass<*>).simpleName!! }}>"}"
|
||||
val code = "@PreviewFeature\ninline fun ${kclass.simpleName}.as${subclass.simpleName}(): $subtype? = this as? $subtype\n" +
|
||||
"@PreviewFeature\ninline fun ${kclass.simpleName}.require${subclass.simpleName}(): $subtype = this as $subtype\n" +
|
||||
"@PreviewFeature\ninline fun <T> ${kclass.simpleName}.when${subclass.simpleName}(block: (${subclass.simpleName}) -> T): $subtype = as${subclass.simpleName}() ?.let(block)"
|
||||
imports to code
|
||||
}
|
||||
}
|
||||
|
||||
val result = mutableMapOf<KClass<*>, Set<KClass<*>>>()
|
||||
|
||||
|
||||
fun main() {
|
||||
result[Message::class] = KlassIndex.getSubclasses(dev.inmo.tgbotapi.CommonAbstracts.WithOptionalLanguageCode::class).toSet()
|
||||
println("import dev.inmo.tgbotapi.utils.PreviewFeature")
|
||||
val importsToFuns = result.keys.flatMap {
|
||||
println("import ${it.qualifiedName}")
|
||||
printlnInstancesSubclassesFuns(it, result.getValue(it))
|
||||
}
|
||||
importsToFuns.forEach { println(it.first) }
|
||||
println()
|
||||
importsToFuns.forEach { println(it.second) }
|
||||
// printlnInstanceSubclassesFuns(Message::class)
|
||||
// printlnInstanceSubclassesFuns(Chat::class)
|
||||
// printlnInstanceSubclassesFuns(CallbackQuery::class)
|
||||
// printlnInstanceSubclassesFuns(KeyboardMarkup::class)
|
||||
// printlnInstanceSubclassesFuns(BotAction::class)
|
||||
// printlnInstanceSubclassesFuns(InlineKeyboardButton::class)
|
||||
// printlnInstanceSubclassesFuns(ChatMember::class)
|
||||
// printlnInstanceSubclassesFuns(TelegramMediaFile::class)
|
||||
// printlnInstanceSubclassesFuns(InlineQuery::class)
|
||||
// printlnInstanceSubclassesFuns(InlineQueryResult::class)
|
||||
// printlnInstanceSubclassesFuns(InputMessageContent::class)
|
||||
// printlnInstanceSubclassesFuns(InputMedia::class)
|
||||
// printlnInstanceSubclassesFuns(Poll::class)
|
||||
// printlnInstanceSubclassesFuns(Update::class)
|
||||
}
|
||||
@@ -1,8 +1,19 @@
|
||||
# TelegramBotAPI extensions
|
||||
|
||||
[ ](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.api/_latestVersion)
|
||||
[](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.api)
|
||||
|
||||
- [TelegramBotAPI extensions](#telegrambotapi-extensions)
|
||||
* [What is it?](#what-is-it)
|
||||
* [Compatibility](#compatibility)
|
||||
* [How to implement library?](#how-to-implement-library)
|
||||
+ [Maven](#maven)
|
||||
+ [Gradle](#gradle)
|
||||
* [Example of usage and comparison with `TelegramBotAPI`](#example-of-usage-and-comparison-with-telegrambotapi)
|
||||
* [Updates](#updates)
|
||||
+ [Alternative way](#alternative-way)
|
||||
|
||||
<small><i><a href='http://ecotrust-canada.github.io/markdown-toc/'>Table of contents generated with markdown-toc</a></i></small>
|
||||
|
||||
## What is it?
|
||||
|
||||
It is wrapper library for [TelegramBotAPI Core](../tgbotapi.core/README.md). Here you can find extensions for
|
||||
|
||||
@@ -1,39 +1,33 @@
|
||||
package dev.inmo.tgbotapi.extensions.api
|
||||
|
||||
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||
import dev.inmo.tgbotapi.extensions.api.get.getFileAdditionalInfo
|
||||
import dev.inmo.tgbotapi.requests.DownloadFile
|
||||
import dev.inmo.tgbotapi.extensions.api.files.downloadFile
|
||||
import dev.inmo.tgbotapi.requests.abstracts.FileId
|
||||
import dev.inmo.tgbotapi.types.files.PathedFile
|
||||
import dev.inmo.tgbotapi.types.files.abstracts.TelegramMediaFile
|
||||
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
|
||||
|
||||
@Deprecated("Replaced", ReplaceWith("downloadFile", "dev.inmo.tgbotapi.extensions.api.files.downloadFile"))
|
||||
suspend fun TelegramBot.downloadFile(
|
||||
filePath: String
|
||||
): ByteArray = execute(
|
||||
DownloadFile(filePath)
|
||||
)
|
||||
): ByteArray = downloadFile(filePath)
|
||||
|
||||
@Deprecated("Replaced", ReplaceWith("downloadFile", "dev.inmo.tgbotapi.extensions.api.files.downloadFile"))
|
||||
suspend fun TelegramBot.downloadFile(
|
||||
pathedFile: PathedFile
|
||||
): ByteArray = execute(
|
||||
DownloadFile(pathedFile.filePath)
|
||||
)
|
||||
): ByteArray = downloadFile(pathedFile)
|
||||
|
||||
@Deprecated("Replaced", ReplaceWith("downloadFile", "dev.inmo.tgbotapi.extensions.api.files.downloadFile"))
|
||||
suspend fun TelegramBot.downloadFile(
|
||||
fileId: FileId
|
||||
): ByteArray = downloadFile(
|
||||
getFileAdditionalInfo(fileId)
|
||||
)
|
||||
): ByteArray = downloadFile(fileId)
|
||||
|
||||
@Deprecated("Replaced", ReplaceWith("downloadFile", "dev.inmo.tgbotapi.extensions.api.files.downloadFile"))
|
||||
suspend fun TelegramBot.downloadFile(
|
||||
file: TelegramMediaFile
|
||||
): ByteArray = downloadFile(
|
||||
getFileAdditionalInfo(file)
|
||||
)
|
||||
): ByteArray = downloadFile(file)
|
||||
|
||||
@Deprecated("Replaced", ReplaceWith("downloadFile", "dev.inmo.tgbotapi.extensions.api.files.downloadFile"))
|
||||
suspend fun TelegramBot.downloadFile(
|
||||
file: MediaContent
|
||||
): ByteArray = downloadFile(
|
||||
getFileAdditionalInfo(file.media)
|
||||
)
|
||||
): ByteArray = downloadFile(file)
|
||||
|
||||
@@ -21,6 +21,10 @@ import kotlinx.coroutines.launch
|
||||
import kotlin.math.ceil
|
||||
|
||||
val defaultLivePeriodDelayMillis = (livePeriodLimit.last - 60L) * 1000L
|
||||
|
||||
/**
|
||||
* @see startLiveLocation
|
||||
*/
|
||||
class LiveLocationProvider internal constructor(
|
||||
private val requestsExecutor: TelegramBot,
|
||||
scope: CoroutineScope,
|
||||
|
||||
@@ -20,3 +20,11 @@ suspend fun TelegramBot.answerCallbackQuery(
|
||||
url: String? = null,
|
||||
cachedTimeSeconds: Int? = null
|
||||
) = answerCallbackQuery(callbackQuery.id, text, showAlert, url, cachedTimeSeconds)
|
||||
|
||||
suspend fun TelegramBot.answer(
|
||||
callbackQuery: CallbackQuery,
|
||||
text: String? = null,
|
||||
showAlert: Boolean? = null,
|
||||
url: String? = null,
|
||||
cachedTimeSeconds: Int? = null
|
||||
) = answerCallbackQuery(callbackQuery.id, text, showAlert, url, cachedTimeSeconds)
|
||||
|
||||
@@ -27,3 +27,13 @@ suspend fun TelegramBot.answerInlineQuery(
|
||||
switchPmText: String? = null,
|
||||
switchPmParameter: String? = null
|
||||
) = answerInlineQuery(inlineQuery.id, results, cachedTime, isPersonal, nextOffset, switchPmText, switchPmParameter)
|
||||
|
||||
suspend fun TelegramBot.answer(
|
||||
inlineQuery: InlineQuery,
|
||||
results: List<InlineQueryResult> = emptyList(),
|
||||
cachedTime: Int? = null,
|
||||
isPersonal: Boolean? = null,
|
||||
nextOffset: String? = null,
|
||||
switchPmText: String? = null,
|
||||
switchPmParameter: String? = null
|
||||
) = answerInlineQuery(inlineQuery.id, results, cachedTime, isPersonal, nextOffset, switchPmText, switchPmParameter)
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package dev.inmo.tgbotapi.extensions.api.files
|
||||
|
||||
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||
import dev.inmo.tgbotapi.extensions.api.get.getFileAdditionalInfo
|
||||
import dev.inmo.tgbotapi.requests.DownloadFile
|
||||
import dev.inmo.tgbotapi.requests.abstracts.FileId
|
||||
import dev.inmo.tgbotapi.types.files.PathedFile
|
||||
import dev.inmo.tgbotapi.types.files.abstracts.TelegramMediaFile
|
||||
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
|
||||
|
||||
suspend fun TelegramBot.downloadFile(
|
||||
filePath: String
|
||||
): ByteArray = execute(
|
||||
DownloadFile(filePath)
|
||||
)
|
||||
|
||||
suspend fun TelegramBot.downloadFile(
|
||||
pathedFile: PathedFile
|
||||
): ByteArray = downloadFile(
|
||||
pathedFile.filePath
|
||||
)
|
||||
|
||||
suspend fun TelegramBot.downloadFile(
|
||||
fileId: FileId
|
||||
): ByteArray = downloadFile(
|
||||
getFileAdditionalInfo(fileId)
|
||||
)
|
||||
|
||||
suspend fun TelegramBot.downloadFile(
|
||||
file: TelegramMediaFile
|
||||
): ByteArray = downloadFile(
|
||||
getFileAdditionalInfo(file)
|
||||
)
|
||||
|
||||
suspend fun TelegramBot.downloadFile(
|
||||
file: MediaContent
|
||||
): ByteArray = downloadFile(
|
||||
getFileAdditionalInfo(file.media)
|
||||
)
|
||||
@@ -0,0 +1,29 @@
|
||||
package dev.inmo.tgbotapi.extensions.api.files
|
||||
|
||||
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||
import dev.inmo.tgbotapi.extensions.api.get.getFileAdditionalInfo
|
||||
import dev.inmo.tgbotapi.requests.DownloadFileStream
|
||||
import dev.inmo.tgbotapi.requests.abstracts.FileId
|
||||
import dev.inmo.tgbotapi.types.files.PathedFile
|
||||
import dev.inmo.tgbotapi.types.files.abstracts.TelegramMediaFile
|
||||
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
|
||||
|
||||
suspend fun TelegramBot.downloadFileStream(
|
||||
filePath: String
|
||||
) = downloadFileStreamAllocator(filePath).invoke()
|
||||
|
||||
suspend fun TelegramBot.downloadFileStream(
|
||||
pathedFile: PathedFile
|
||||
) = downloadFileStream(pathedFile.filePath)
|
||||
|
||||
suspend fun TelegramBot.downloadFileStream(
|
||||
fileId: FileId
|
||||
) = downloadFileStream(getFileAdditionalInfo(fileId))
|
||||
|
||||
suspend fun TelegramBot.downloadFileStream(
|
||||
file: TelegramMediaFile
|
||||
) = downloadFileStream(getFileAdditionalInfo(file))
|
||||
|
||||
suspend fun TelegramBot.downloadFileStream(
|
||||
file: MediaContent
|
||||
) = downloadFileStream(getFileAdditionalInfo(file.media))
|
||||
@@ -0,0 +1,29 @@
|
||||
package dev.inmo.tgbotapi.extensions.api.files
|
||||
|
||||
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||
import dev.inmo.tgbotapi.extensions.api.get.getFileAdditionalInfo
|
||||
import dev.inmo.tgbotapi.requests.DownloadFileStream
|
||||
import dev.inmo.tgbotapi.requests.abstracts.FileId
|
||||
import dev.inmo.tgbotapi.types.files.PathedFile
|
||||
import dev.inmo.tgbotapi.types.files.abstracts.TelegramMediaFile
|
||||
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
|
||||
|
||||
suspend fun TelegramBot.downloadFileStreamAllocator(
|
||||
filePath: String
|
||||
) = execute(DownloadFileStream(filePath))
|
||||
|
||||
suspend fun TelegramBot.downloadFileStreamAllocator(
|
||||
pathedFile: PathedFile
|
||||
) = downloadFileStreamAllocator(pathedFile.filePath)
|
||||
|
||||
suspend fun TelegramBot.downloadFileStreamAllocator(
|
||||
fileId: FileId
|
||||
) = downloadFileStreamAllocator(getFileAdditionalInfo(fileId))
|
||||
|
||||
suspend fun TelegramBot.downloadFileStreamAllocator(
|
||||
file: TelegramMediaFile
|
||||
) = downloadFileStreamAllocator(getFileAdditionalInfo(file))
|
||||
|
||||
suspend fun TelegramBot.downloadFileStreamAllocator(
|
||||
file: MediaContent
|
||||
) = downloadFileStreamAllocator(getFileAdditionalInfo(file.media))
|
||||
@@ -4,6 +4,7 @@ import dev.inmo.tgbotapi.bot.TelegramBot
|
||||
import dev.inmo.tgbotapi.requests.abstracts.FileId
|
||||
import dev.inmo.tgbotapi.requests.get.GetFile
|
||||
import dev.inmo.tgbotapi.types.files.abstracts.TelegramMediaFile
|
||||
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
|
||||
|
||||
suspend fun TelegramBot.getFileAdditionalInfo(
|
||||
fileId: FileId
|
||||
@@ -14,3 +15,7 @@ suspend fun TelegramBot.getFileAdditionalInfo(
|
||||
suspend fun TelegramBot.getFileAdditionalInfo(
|
||||
file: TelegramMediaFile
|
||||
) = getFileAdditionalInfo(file.fileId)
|
||||
|
||||
suspend fun TelegramBot.getFileAdditionalInfo(
|
||||
content: MediaContent
|
||||
) = getFileAdditionalInfo(content.media)
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package dev.inmo.tgbotapi.extensions.api.send
|
||||
|
||||
import dev.inmo.micro_utils.coroutines.safely
|
||||
import dev.inmo.micro_utils.coroutines.safelyWithoutExceptions
|
||||
import dev.inmo.micro_utils.coroutines.*
|
||||
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||
import dev.inmo.tgbotapi.requests.send.SendAction
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.actions.*
|
||||
import dev.inmo.tgbotapi.types.chat.abstracts.Chat
|
||||
import kotlinx.coroutines.*
|
||||
import kotlin.coroutines.coroutineContext
|
||||
|
||||
private const val refreshTime: MilliSeconds = (botActionActualityTime - 1) * 1000L
|
||||
typealias TelegramBotActionCallback<T> = suspend TelegramBot.() -> T
|
||||
@@ -16,21 +16,17 @@ suspend fun <T> TelegramBot.withAction(
|
||||
actionRequest: SendAction,
|
||||
block: TelegramBotActionCallback<T>
|
||||
): T {
|
||||
val botActionJob = supervisorScope {
|
||||
launch {
|
||||
while (isActive) {
|
||||
delay(refreshTime)
|
||||
safelyWithoutExceptions {
|
||||
execute(actionRequest)
|
||||
}
|
||||
val botActionJob = CoroutineScope(coroutineContext).launch {
|
||||
while (isActive) {
|
||||
delay(refreshTime)
|
||||
safelyWithoutExceptions {
|
||||
execute(actionRequest)
|
||||
}
|
||||
}
|
||||
}
|
||||
return try {
|
||||
safely { block() }
|
||||
} finally {
|
||||
botActionJob.cancel()
|
||||
}
|
||||
val result = safelyWithResult { block() }
|
||||
botActionJob.cancel()
|
||||
return result.getOrThrow()
|
||||
}
|
||||
|
||||
suspend fun <T> TelegramBot.withAction(
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package dev.inmo.tgbotapi.extensions.api.files
|
||||
|
||||
import dev.inmo.micro_utils.coroutines.doOutsideOfCoroutine
|
||||
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||
import dev.inmo.tgbotapi.extensions.api.get.getFileAdditionalInfo
|
||||
import dev.inmo.tgbotapi.requests.abstracts.FileId
|
||||
import dev.inmo.tgbotapi.types.files.PathedFile
|
||||
import dev.inmo.tgbotapi.types.files.abstracts.TelegramMediaFile
|
||||
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
|
||||
import io.ktor.util.cio.use
|
||||
import io.ktor.util.cio.writeChannel
|
||||
import io.ktor.utils.io.copyTo
|
||||
import kotlinx.coroutines.job
|
||||
import java.io.File
|
||||
import kotlin.coroutines.coroutineContext
|
||||
|
||||
suspend fun TelegramBot.downloadFile(
|
||||
filePath: String,
|
||||
destFile: File
|
||||
): File {
|
||||
val readChannel = downloadFileStream(filePath)
|
||||
|
||||
destFile.deleteRecursively()
|
||||
destFile.parentFile.mkdirs()
|
||||
doOutsideOfCoroutine { destFile.createNewFile() }
|
||||
|
||||
destFile.writeChannel(coroutineContext.job).use {
|
||||
readChannel.copyTo(this)
|
||||
}
|
||||
|
||||
return destFile
|
||||
}
|
||||
|
||||
suspend fun TelegramBot.downloadFile(
|
||||
pathedFile: PathedFile,
|
||||
destFile: File
|
||||
) = downloadFile(
|
||||
pathedFile.filePath,
|
||||
destFile
|
||||
)
|
||||
|
||||
suspend fun TelegramBot.downloadFile(
|
||||
fileId: FileId,
|
||||
destFile: File
|
||||
) = downloadFile(
|
||||
getFileAdditionalInfo(fileId),
|
||||
destFile
|
||||
)
|
||||
|
||||
suspend fun TelegramBot.downloadFile(
|
||||
file: TelegramMediaFile,
|
||||
destFile: File
|
||||
): File = downloadFile(
|
||||
getFileAdditionalInfo(file),
|
||||
destFile
|
||||
)
|
||||
|
||||
suspend fun TelegramBot.downloadFile(
|
||||
file: MediaContent,
|
||||
destFile: File
|
||||
) = downloadFile(
|
||||
getFileAdditionalInfo(file.media),
|
||||
destFile
|
||||
)
|
||||
@@ -1,5 +1,16 @@
|
||||
# TelegramBotAPI Behaviour Builder Extensions
|
||||
|
||||
[](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.behaviour_builder)
|
||||
|
||||
- [TelegramBotAPI Behaviour Builder Extensions](#telegrambotapi-behaviour-builder-extensions)
|
||||
* [What is it?](#what-is-it)
|
||||
* [Triggers](#triggers)
|
||||
* [Waiters](#waiters)
|
||||
|
||||
<small><i><a href='http://ecotrust-canada.github.io/markdown-toc/'>Table of contents generated with markdown-toc</a></i></small>
|
||||
|
||||
## What is it?
|
||||
|
||||
This extension was created to make it more simple to build bot steps handling. Usually, you must use something like:
|
||||
|
||||
```kotlin
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
@file:Suppress("NOTHING_TO_INLINE")
|
||||
|
||||
package dev.inmo.tgbotapi.extensions.behaviour_builder
|
||||
|
||||
import dev.inmo.micro_utils.coroutines.*
|
||||
@@ -10,6 +12,13 @@ import kotlinx.coroutines.flow.filter
|
||||
|
||||
typealias BehaviourContextReceiver<T> = suspend BehaviourContext.() -> T
|
||||
typealias BehaviourContextAndTypeReceiver<T, I> = suspend BehaviourContext.(I) -> T
|
||||
typealias BehaviourContextAndTwoTypesReceiver<T, I1, I2> = suspend BehaviourContext.(I1, I2) -> T
|
||||
inline fun <T> BehaviourContextReceiver(noinline block: BehaviourContextReceiver<T>) = block
|
||||
inline fun <T, I> BehaviourContextAndTypeReceiver(noinline block: BehaviourContextAndTypeReceiver<T, I>) = block
|
||||
inline fun <T, I1, I2> BehaviourContextAndTwoTypesReceiver(noinline block: BehaviourContextAndTwoTypesReceiver<T, I1, I2>) = block
|
||||
internal inline fun <T, I1, I2> BehaviourContextAndTwoTypesReceiver<T, I1, I2>.toOneType(
|
||||
i1: I1,
|
||||
): BehaviourContextAndTypeReceiver<T, I2> = { invoke(this, i1, it) }
|
||||
|
||||
/**
|
||||
* This class contains all necessary tools for work with bots and especially for [buildBehaviour]
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations
|
||||
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter
|
||||
import dev.inmo.tgbotapi.extensions.utils.asCallbackQueryUpdate
|
||||
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||
import dev.inmo.tgbotapi.types.CallbackQuery.*
|
||||
@@ -14,13 +15,19 @@ private suspend fun <O> BehaviourContext.waitCallbackQueries(
|
||||
count: Int = 1,
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
filter: SimpleFilter<CallbackQuery>? = null,
|
||||
mapper: suspend CallbackQuery.() -> O?
|
||||
): List<O> = expectFlow(
|
||||
initRequest,
|
||||
count,
|
||||
errorFactory
|
||||
) {
|
||||
it.asCallbackQueryUpdate() ?.data ?.mapper().let(::listOfNotNull)
|
||||
val data = it.asCallbackQueryUpdate() ?.data
|
||||
if (data != null && (filter == null || filter(data))) {
|
||||
data.mapper().let(::listOfNotNull)
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}.toList().toList()
|
||||
|
||||
|
||||
@@ -28,17 +35,23 @@ private suspend inline fun <reified T : CallbackQuery> BehaviourContext.waitCall
|
||||
count: Int = 1,
|
||||
initRequest: Request<*>? = null,
|
||||
noinline errorFactory: NullableRequestBuilder<*> = { null },
|
||||
noinline filter: CallbackQueryMapper<T>? = null
|
||||
noinline filter: SimpleFilter<T>? = null,
|
||||
noinline mapper: CallbackQueryMapper<T>? = null
|
||||
) : List<T> = waitCallbackQueries<T>(
|
||||
count,
|
||||
initRequest,
|
||||
errorFactory
|
||||
errorFactory,
|
||||
filter ?.let {
|
||||
{
|
||||
(it as? T) ?.let { filter(it) } == true
|
||||
}
|
||||
}
|
||||
) {
|
||||
if (this is T) {
|
||||
if (filter == null) {
|
||||
if (mapper == null) {
|
||||
this
|
||||
} else {
|
||||
filter(this)
|
||||
mapper(this)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
@@ -50,53 +63,62 @@ suspend fun BehaviourContext.waitDataCallbackQuery(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: CallbackQueryMapper<DataCallbackQuery>? = null
|
||||
) = waitCallbacks(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<DataCallbackQuery>? = null,
|
||||
mapper: CallbackQueryMapper<DataCallbackQuery>? = null
|
||||
) = waitCallbacks(count, initRequest, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitGameShortNameCallbackQuery(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: CallbackQueryMapper<GameShortNameCallbackQuery>? = null
|
||||
) = waitCallbacks(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<GameShortNameCallbackQuery>? = null,
|
||||
mapper: CallbackQueryMapper<GameShortNameCallbackQuery>? = null
|
||||
) = waitCallbacks(count, initRequest, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitInlineMessageIdCallbackQuery(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: CallbackQueryMapper<InlineMessageIdCallbackQuery>? = null
|
||||
) = waitCallbacks(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<InlineMessageIdCallbackQuery>? = null,
|
||||
mapper: CallbackQueryMapper<InlineMessageIdCallbackQuery>? = null
|
||||
) = waitCallbacks(count, initRequest, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitInlineMessageIdDataCallbackQuery(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: CallbackQueryMapper<InlineMessageIdDataCallbackQuery>? = null
|
||||
) = waitCallbacks(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<InlineMessageIdDataCallbackQuery>? = null,
|
||||
mapper: CallbackQueryMapper<InlineMessageIdDataCallbackQuery>? = null
|
||||
) = waitCallbacks(count, initRequest, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitInlineMessageIdGameShortNameCallbackQuery(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: CallbackQueryMapper<InlineMessageIdGameShortNameCallbackQuery>? = null
|
||||
) = waitCallbacks(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<InlineMessageIdGameShortNameCallbackQuery>? = null,
|
||||
mapper: CallbackQueryMapper<InlineMessageIdGameShortNameCallbackQuery>? = null
|
||||
) = waitCallbacks(count, initRequest, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitMessageCallbackQuery(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: CallbackQueryMapper<MessageCallbackQuery>? = null
|
||||
) = waitCallbacks(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<MessageCallbackQuery>? = null,
|
||||
mapper: CallbackQueryMapper<MessageCallbackQuery>? = null
|
||||
) = waitCallbacks(count, initRequest, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitMessageDataCallbackQuery(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: CallbackQueryMapper<MessageDataCallbackQuery>? = null
|
||||
) = waitCallbacks(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<MessageDataCallbackQuery>? = null,
|
||||
mapper: CallbackQueryMapper<MessageDataCallbackQuery>? = null
|
||||
) = waitCallbacks(count, initRequest, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitMessageGameShortNameCallbackQuery(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: CallbackQueryMapper<MessageGameShortNameCallbackQuery>? = null
|
||||
) = waitCallbacks(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<MessageGameShortNameCallbackQuery>? = null,
|
||||
mapper: CallbackQueryMapper<MessageGameShortNameCallbackQuery>? = null
|
||||
) = waitCallbacks(count, initRequest, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitUnknownCallbackQuery(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: CallbackQueryMapper<UnknownCallbackQueryType>? = null
|
||||
) = waitCallbacks(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<UnknownCallbackQueryType>? = null,
|
||||
mapper: CallbackQueryMapper<UnknownCallbackQueryType>? = null
|
||||
) = waitCallbacks(count, initRequest, errorFactory, filter, mapper)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations
|
||||
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter
|
||||
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||
import dev.inmo.tgbotapi.types.ChatMemberUpdated
|
||||
import dev.inmo.tgbotapi.types.update.CommonChatMemberUpdatedUpdate
|
||||
@@ -14,29 +15,37 @@ private suspend inline fun <reified T : ChatMemberUpdatedUpdate> BehaviourContex
|
||||
count: Int = 1,
|
||||
initRequest: Request<*>? = null,
|
||||
noinline errorFactory: NullableRequestBuilder<*> = { null },
|
||||
noinline filter: SimpleFilter<T>? = null,
|
||||
noinline mapper: ChatMemberUpdatedMapper<ChatMemberUpdated>
|
||||
): List<ChatMemberUpdated> = expectFlow(
|
||||
initRequest,
|
||||
count,
|
||||
errorFactory
|
||||
) {
|
||||
(it as? T) ?.data.let(::listOfNotNull)
|
||||
val casted = (it as? T) ?: return@expectFlow emptyList()
|
||||
if (filter == null || filter(casted)) {
|
||||
casted.data.mapper().let(::listOfNotNull)
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}.toList().toList()
|
||||
|
||||
private suspend inline fun <reified T : ChatMemberUpdatedUpdate> BehaviourContext.waitChatMemberUpdatedWithFilter(
|
||||
count: Int = 1,
|
||||
initRequest: Request<*>? = null,
|
||||
noinline errorFactory: NullableRequestBuilder<*> = { null },
|
||||
noinline filter: ChatMemberUpdatedMapper<ChatMemberUpdated>? = null
|
||||
noinline filter: SimpleFilter<T>? = null,
|
||||
noinline mapper: ChatMemberUpdatedMapper<ChatMemberUpdated>? = null
|
||||
) : List<ChatMemberUpdated> = waitChatMemberUpdated<T>(
|
||||
count,
|
||||
initRequest,
|
||||
errorFactory
|
||||
errorFactory,
|
||||
filter,
|
||||
) {
|
||||
if (filter == null) {
|
||||
if (mapper == null) {
|
||||
this
|
||||
} else {
|
||||
filter(this)
|
||||
mapper(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,19 +53,22 @@ suspend fun BehaviourContext.waitChatMemberUpdated(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: ChatMemberUpdatedMapper<ChatMemberUpdated>? = null
|
||||
) = waitChatMemberUpdatedWithFilter<ChatMemberUpdatedUpdate>(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<ChatMemberUpdatedUpdate>? = null,
|
||||
mapper: ChatMemberUpdatedMapper<ChatMemberUpdated>? = null
|
||||
) = waitChatMemberUpdatedWithFilter<ChatMemberUpdatedUpdate>(count, initRequest, errorFactory, filter, mapper)
|
||||
|
||||
suspend fun BehaviourContext.waitCommonChatMemberUpdated(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: ChatMemberUpdatedMapper<ChatMemberUpdated>? = null
|
||||
) = waitChatMemberUpdatedWithFilter<CommonChatMemberUpdatedUpdate>(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<CommonChatMemberUpdatedUpdate>? = null,
|
||||
mapper: ChatMemberUpdatedMapper<ChatMemberUpdated>? = null
|
||||
) = waitChatMemberUpdatedWithFilter<CommonChatMemberUpdatedUpdate>(count, initRequest, errorFactory, filter, mapper)
|
||||
|
||||
suspend fun BehaviourContext.waitMyChatMemberUpdated(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: ChatMemberUpdatedMapper<ChatMemberUpdated>? = null
|
||||
) = waitChatMemberUpdatedWithFilter<MyChatMemberUpdatedUpdate>(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<MyChatMemberUpdatedUpdate>? = null,
|
||||
mapper: ChatMemberUpdatedMapper<ChatMemberUpdated>? = null
|
||||
) = waitChatMemberUpdatedWithFilter<MyChatMemberUpdatedUpdate>(count, initRequest, errorFactory, filter, mapper)
|
||||
|
||||
@@ -4,13 +4,16 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations
|
||||
|
||||
import dev.inmo.micro_utils.coroutines.safelyWithoutExceptions
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||
import dev.inmo.tgbotapi.extensions.utils.*
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter
|
||||
import dev.inmo.tgbotapi.extensions.utils.withContent
|
||||
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage
|
||||
import dev.inmo.tgbotapi.types.message.content.*
|
||||
import dev.inmo.tgbotapi.types.message.content.abstracts.*
|
||||
import dev.inmo.tgbotapi.types.message.content.media.*
|
||||
import dev.inmo.tgbotapi.types.message.payments.InvoiceContent
|
||||
import dev.inmo.tgbotapi.types.update.MediaGroupUpdates.SentMediaGroupUpdate
|
||||
import dev.inmo.tgbotapi.types.update.abstracts.BaseSentMessageUpdate
|
||||
import kotlinx.coroutines.flow.toList
|
||||
|
||||
typealias CommonMessageToContentMapper<T> = suspend CommonMessage<T>.() -> T?
|
||||
@@ -20,184 +23,245 @@ private suspend fun <O> BehaviourContext.waitCommonMessage(
|
||||
initRequest: Request<*>? = null,
|
||||
includeMediaGroups: Boolean = true,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
filter: SimpleFilter<CommonMessage<MessageContent>>? = null,
|
||||
mapper: suspend CommonMessage<MessageContent>.() -> O?
|
||||
): List<O> = expectFlow(
|
||||
initRequest,
|
||||
count,
|
||||
errorFactory
|
||||
) {
|
||||
if (includeMediaGroups) {
|
||||
it.asSentMediaGroupUpdate() ?.data ?.mapNotNull {
|
||||
(it as CommonMessage<MessageContent>).mapper()
|
||||
} ?.let { return@expectFlow it }
|
||||
val messages = when (it) {
|
||||
is SentMediaGroupUpdate -> {
|
||||
if (includeMediaGroups) {
|
||||
it.data.map { it as CommonMessage<MessageContent> }
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
is BaseSentMessageUpdate -> listOf(it.data)
|
||||
else -> return@expectFlow emptyList()
|
||||
}
|
||||
messages.mapNotNull { message ->
|
||||
val asCommonMessage = message as CommonMessage<MessageContent>
|
||||
if (filter == null || filter(asCommonMessage)) {
|
||||
asCommonMessage.mapper()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
it.asBaseSentMessageUpdate() ?.data ?.asCommonMessage() ?.mapper().let(::listOfNotNull)
|
||||
}.toList().toList()
|
||||
|
||||
private suspend inline fun <reified T : MessageContent> BehaviourContext.waitContent(
|
||||
count: Int = 1,
|
||||
initRequest: Request<*>? = null,
|
||||
includeMediaGroups: Boolean = true,
|
||||
noinline errorFactory: NullableRequestBuilder<*> = { null },
|
||||
noinline filter: CommonMessageToContentMapper<T>? = null
|
||||
) : List<T> = waitCommonMessage<T>(
|
||||
count,
|
||||
initRequest,
|
||||
includeMediaGroups,
|
||||
errorFactory
|
||||
) {
|
||||
internal inline fun <reified T : MessageContent> contentConverter(
|
||||
noinline mapper: CommonMessageToContentMapper<T>? = null
|
||||
): suspend CommonMessage<MessageContent>.() -> T? = {
|
||||
if (content is T) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val message = (this as CommonMessage<T>)
|
||||
if (filter == null) {
|
||||
if (mapper == null) {
|
||||
message.content
|
||||
} else {
|
||||
safelyWithoutExceptions { filter(message) }
|
||||
safelyWithoutExceptions { mapper(message) }
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private suspend inline fun <reified T : MessageContent> BehaviourContext.waitContent(
|
||||
count: Int = 1,
|
||||
initRequest: Request<*>? = null,
|
||||
includeMediaGroups: Boolean = true,
|
||||
noinline errorFactory: NullableRequestBuilder<*> = { null },
|
||||
noinline filter: SimpleFilter<CommonMessage<T>>? = null,
|
||||
noinline mapper: CommonMessageToContentMapper<T>? = null
|
||||
) : List<T> = waitCommonMessage<T>(
|
||||
count,
|
||||
initRequest,
|
||||
includeMediaGroups,
|
||||
errorFactory,
|
||||
filter ?.let {
|
||||
{
|
||||
it.withContent<T>() ?.let { filter(it) } == true
|
||||
}
|
||||
},
|
||||
contentConverter(mapper)
|
||||
)
|
||||
|
||||
suspend fun BehaviourContext.waitContentMessage(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
includeMediaGroups: Boolean = true,
|
||||
filter: CommonMessageToContentMapper<MessageContent>? = null
|
||||
) = waitContent(count, initRequest, includeMediaGroups, errorFactory, filter)
|
||||
filter: SimpleFilter<CommonMessage<MessageContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<MessageContent>? = null
|
||||
) = waitContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitContact(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: CommonMessageToContentMapper<ContactContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter)
|
||||
filter: SimpleFilter<CommonMessage<ContactContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<ContactContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitDice(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: CommonMessageToContentMapper<DiceContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter)
|
||||
filter: SimpleFilter<CommonMessage<DiceContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<DiceContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitGame(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: CommonMessageToContentMapper<GameContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter)
|
||||
filter: SimpleFilter<CommonMessage<GameContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<GameContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitLocation(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: CommonMessageToContentMapper<LocationContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter)
|
||||
filter: SimpleFilter<CommonMessage<LocationContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<LocationContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitLiveLocation(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: SimpleFilter<CommonMessage<LiveLocationContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<LiveLocationContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitStaticLocation(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: SimpleFilter<CommonMessage<StaticLocationContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<StaticLocationContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitPoll(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: CommonMessageToContentMapper<PollContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter)
|
||||
filter: SimpleFilter<CommonMessage<PollContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<PollContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitText(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: CommonMessageToContentMapper<TextContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter)
|
||||
filter: SimpleFilter<CommonMessage<TextContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<TextContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitVenue(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: CommonMessageToContentMapper<VenueContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter)
|
||||
filter: SimpleFilter<CommonMessage<VenueContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<VenueContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitAudioMediaGroupContent(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
includeMediaGroups: Boolean = true,
|
||||
filter: CommonMessageToContentMapper<AudioMediaGroupContent>? = null
|
||||
) = waitContent(count, initRequest, includeMediaGroups, errorFactory, filter)
|
||||
filter: SimpleFilter<CommonMessage<AudioMediaGroupContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<AudioMediaGroupContent>? = null
|
||||
) = waitContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitDocumentMediaGroupContent(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
includeMediaGroups: Boolean = true,
|
||||
filter: CommonMessageToContentMapper<DocumentMediaGroupContent>? = null
|
||||
) = waitContent(count, initRequest, includeMediaGroups, errorFactory, filter)
|
||||
filter: SimpleFilter<CommonMessage<DocumentMediaGroupContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<DocumentMediaGroupContent>? = null
|
||||
) = waitContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitMedia(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
includeMediaGroups: Boolean = false,
|
||||
filter: CommonMessageToContentMapper<MediaContent>? = null
|
||||
) = waitContent(count, initRequest, includeMediaGroups, errorFactory, filter)
|
||||
filter: SimpleFilter<CommonMessage<MediaContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<MediaContent>? = null
|
||||
) = waitContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitAnyMediaGroupContent(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
includeMediaGroups: Boolean = true,
|
||||
filter: CommonMessageToContentMapper<MediaGroupContent>? = null
|
||||
) = waitContent(count, initRequest, includeMediaGroups, errorFactory, filter)
|
||||
filter: SimpleFilter<CommonMessage<MediaGroupContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<MediaGroupContent>? = null
|
||||
) = waitContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitVisualMediaGroupContent(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
includeMediaGroups: Boolean = true,
|
||||
filter: CommonMessageToContentMapper<VisualMediaGroupContent>? = null
|
||||
) = waitContent(count, initRequest, includeMediaGroups, errorFactory, filter)
|
||||
filter: SimpleFilter<CommonMessage<VisualMediaGroupContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<VisualMediaGroupContent>? = null
|
||||
) = waitContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitAnimation(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: CommonMessageToContentMapper<AnimationContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter)
|
||||
filter: SimpleFilter<CommonMessage<AnimationContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<AnimationContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitAudio(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
includeMediaGroups: Boolean = false,
|
||||
filter: CommonMessageToContentMapper<AudioContent>? = null
|
||||
) = waitContent(count, initRequest, includeMediaGroups, errorFactory, filter)
|
||||
filter: SimpleFilter<CommonMessage<AudioContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<AudioContent>? = null
|
||||
) = waitContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitDocument(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
includeMediaGroups: Boolean = false,
|
||||
filter: CommonMessageToContentMapper<DocumentContent>? = null
|
||||
) = waitContent(count, initRequest, includeMediaGroups, errorFactory, filter)
|
||||
filter: SimpleFilter<CommonMessage<DocumentContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<DocumentContent>? = null
|
||||
) = waitContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitPhoto(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
includeMediaGroups: Boolean = false,
|
||||
filter: CommonMessageToContentMapper<PhotoContent>? = null
|
||||
) = waitContent(count, initRequest, includeMediaGroups, errorFactory, filter)
|
||||
filter: SimpleFilter<CommonMessage<PhotoContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<PhotoContent>? = null
|
||||
) = waitContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitSticker(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: CommonMessageToContentMapper<StickerContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter)
|
||||
filter: SimpleFilter<CommonMessage<StickerContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<StickerContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitVideo(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
includeMediaGroups: Boolean = false,
|
||||
filter: CommonMessageToContentMapper<VideoContent>? = null
|
||||
) = waitContent(count, initRequest, includeMediaGroups, errorFactory, filter)
|
||||
filter: SimpleFilter<CommonMessage<VideoContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<VideoContent>? = null
|
||||
) = waitContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitVideoNote(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: CommonMessageToContentMapper<VideoNoteContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter)
|
||||
filter: SimpleFilter<CommonMessage<VideoNoteContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<VideoNoteContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitVoice(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: CommonMessageToContentMapper<VoiceContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter)
|
||||
filter: SimpleFilter<CommonMessage<VoiceContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<VoiceContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitInvoice(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: CommonMessageToContentMapper<InvoiceContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter)
|
||||
filter: SimpleFilter<CommonMessage<InvoiceContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<InvoiceContent>? = null
|
||||
) = waitContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
|
||||
@@ -0,0 +1,249 @@
|
||||
@file:Suppress("unused")
|
||||
|
||||
package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations
|
||||
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter
|
||||
import dev.inmo.tgbotapi.extensions.utils.asCommonMessage
|
||||
import dev.inmo.tgbotapi.extensions.utils.withContent
|
||||
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.MediaGroupMessage
|
||||
import dev.inmo.tgbotapi.types.message.content.*
|
||||
import dev.inmo.tgbotapi.types.message.content.abstracts.*
|
||||
import dev.inmo.tgbotapi.types.message.content.media.*
|
||||
import dev.inmo.tgbotapi.types.message.payments.InvoiceContent
|
||||
import dev.inmo.tgbotapi.types.update.abstracts.BaseEditMessageUpdate
|
||||
import kotlinx.coroutines.flow.toList
|
||||
|
||||
private suspend fun <O> BehaviourContext.waitEditedCommonMessage(
|
||||
count: Int = 1,
|
||||
initRequest: Request<*>? = null,
|
||||
includeMediaGroups: Boolean = true,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
filter: SimpleFilter<CommonMessage<MessageContent>>? = null,
|
||||
mapper: suspend CommonMessage<MessageContent>.() -> O?
|
||||
): List<O> = expectFlow(
|
||||
initRequest,
|
||||
count,
|
||||
errorFactory
|
||||
) {
|
||||
val messages = when (it) {
|
||||
is BaseEditMessageUpdate -> {
|
||||
val commonMessage = it.data.asCommonMessage()
|
||||
if (commonMessage !is MediaGroupMessage<*> || includeMediaGroups) {
|
||||
listOf(commonMessage)
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
else -> return@expectFlow emptyList()
|
||||
}
|
||||
messages.mapNotNull { message ->
|
||||
val asCommonMessage = message as CommonMessage<MessageContent>
|
||||
if (filter == null || filter(asCommonMessage)) {
|
||||
asCommonMessage.mapper()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}.toList().toList()
|
||||
|
||||
private suspend inline fun <reified T : MessageContent> BehaviourContext.waitEditedContent(
|
||||
count: Int = 1,
|
||||
initRequest: Request<*>? = null,
|
||||
includeMediaGroups: Boolean = true,
|
||||
noinline errorFactory: NullableRequestBuilder<*> = { null },
|
||||
noinline filter: SimpleFilter<CommonMessage<T>>? = null,
|
||||
noinline mapper: CommonMessageToContentMapper<T>? = null
|
||||
) : List<T> = waitEditedCommonMessage<T>(
|
||||
count,
|
||||
initRequest,
|
||||
includeMediaGroups,
|
||||
errorFactory,
|
||||
filter ?.let {
|
||||
{
|
||||
it.withContent<T>() ?.let { filter(it) } == true
|
||||
}
|
||||
},
|
||||
contentConverter(mapper)
|
||||
)
|
||||
|
||||
suspend fun BehaviourContext.waitEditedContentMessage(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
includeMediaGroups: Boolean = true,
|
||||
filter: SimpleFilter<CommonMessage<MessageContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<MessageContent>? = null
|
||||
) = waitEditedContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitEditedContact(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: SimpleFilter<CommonMessage<ContactContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<ContactContent>? = null
|
||||
) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitEditedDice(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: SimpleFilter<CommonMessage<DiceContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<DiceContent>? = null
|
||||
) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitEditedGame(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: SimpleFilter<CommonMessage<GameContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<GameContent>? = null
|
||||
) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitEditedLocation(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: SimpleFilter<CommonMessage<LocationContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<LocationContent>? = null
|
||||
) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitEditedLiveLocation(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: SimpleFilter<CommonMessage<LiveLocationContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<LiveLocationContent>? = null
|
||||
) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitEditedStaticLocation(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: SimpleFilter<CommonMessage<StaticLocationContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<StaticLocationContent>? = null
|
||||
) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitEditedPoll(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: SimpleFilter<CommonMessage<PollContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<PollContent>? = null
|
||||
) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitEditedText(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: SimpleFilter<CommonMessage<TextContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<TextContent>? = null
|
||||
) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitEditedVenue(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: SimpleFilter<CommonMessage<VenueContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<VenueContent>? = null
|
||||
) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitEditedAudioMediaGroupContent(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
includeMediaGroups: Boolean = true,
|
||||
filter: SimpleFilter<CommonMessage<AudioMediaGroupContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<AudioMediaGroupContent>? = null
|
||||
) = waitEditedContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitEditedDocumentMediaGroupContent(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
includeMediaGroups: Boolean = true,
|
||||
filter: SimpleFilter<CommonMessage<DocumentMediaGroupContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<DocumentMediaGroupContent>? = null
|
||||
) = waitEditedContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitEditedMedia(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
includeMediaGroups: Boolean = false,
|
||||
filter: SimpleFilter<CommonMessage<MediaContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<MediaContent>? = null
|
||||
) = waitEditedContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitEditedAnyMediaGroupContent(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
includeMediaGroups: Boolean = true,
|
||||
filter: SimpleFilter<CommonMessage<MediaGroupContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<MediaGroupContent>? = null
|
||||
) = waitEditedContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitEditedVisualMediaGroupContent(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
includeMediaGroups: Boolean = true,
|
||||
filter: SimpleFilter<CommonMessage<VisualMediaGroupContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<VisualMediaGroupContent>? = null
|
||||
) = waitEditedContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitEditedAnimation(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: SimpleFilter<CommonMessage<AnimationContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<AnimationContent>? = null
|
||||
) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitEditedAudio(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
includeMediaGroups: Boolean = false,
|
||||
filter: SimpleFilter<CommonMessage<AudioContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<AudioContent>? = null
|
||||
) = waitEditedContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitEditedDocument(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
includeMediaGroups: Boolean = false,
|
||||
filter: SimpleFilter<CommonMessage<DocumentContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<DocumentContent>? = null
|
||||
) = waitEditedContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitEditedPhoto(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
includeMediaGroups: Boolean = false,
|
||||
filter: SimpleFilter<CommonMessage<PhotoContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<PhotoContent>? = null
|
||||
) = waitEditedContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitEditedSticker(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: SimpleFilter<CommonMessage<StickerContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<StickerContent>? = null
|
||||
) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitEditedVideo(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
includeMediaGroups: Boolean = false,
|
||||
filter: SimpleFilter<CommonMessage<VideoContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<VideoContent>? = null
|
||||
) = waitEditedContent(count, initRequest, includeMediaGroups, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitEditedVideoNote(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: SimpleFilter<CommonMessage<VideoNoteContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<VideoNoteContent>? = null
|
||||
) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitEditedVoice(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: SimpleFilter<CommonMessage<VoiceContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<VoiceContent>? = null
|
||||
) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitEditedInvoice(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: SimpleFilter<CommonMessage<InvoiceContent>>? = null,
|
||||
mapper: CommonMessageToContentMapper<InvoiceContent>? = null
|
||||
) = waitEditedContent(count, initRequest, false, errorFactory, filter, mapper)
|
||||
@@ -3,6 +3,7 @@
|
||||
package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations
|
||||
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter
|
||||
import dev.inmo.tgbotapi.extensions.utils.asBaseSentMessageUpdate
|
||||
import dev.inmo.tgbotapi.extensions.utils.asChatEventMessage
|
||||
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||
@@ -18,13 +19,19 @@ private suspend fun <O> BehaviourContext.waitEventMessages(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: SimpleFilter<ChatEventMessage<ChatEvent>>? = null,
|
||||
mapper: suspend ChatEventMessage<ChatEvent>.() -> O?
|
||||
): List<O> = expectFlow(
|
||||
initRequest,
|
||||
count,
|
||||
errorFactory
|
||||
) {
|
||||
it.asBaseSentMessageUpdate() ?.data ?.asChatEventMessage() ?.mapper().let(::listOfNotNull)
|
||||
val data = it.asBaseSentMessageUpdate() ?.data ?.asChatEventMessage()
|
||||
if (data != null && (filter == null || filter(data))) {
|
||||
data.mapper().let(::listOfNotNull)
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}.toList().toList()
|
||||
|
||||
|
||||
@@ -32,19 +39,25 @@ private suspend inline fun <reified T : ChatEvent> BehaviourContext.waitEvents(
|
||||
count: Int = 1,
|
||||
initRequest: Request<*>? = null,
|
||||
noinline errorFactory: NullableRequestBuilder<*> = { null },
|
||||
noinline filter: EventMessageToEventMapper<T>? = null
|
||||
noinline filter: SimpleFilter<ChatEventMessage<T>>? = null,
|
||||
noinline mapper: EventMessageToEventMapper<T>? = null
|
||||
) : List<T> = waitEventMessages<T>(
|
||||
initRequest,
|
||||
errorFactory,
|
||||
count
|
||||
count,
|
||||
filter ?.let {
|
||||
{
|
||||
(it.chatEvent as? T) ?.let { filter(it as ChatEventMessage<T>) } == true
|
||||
}
|
||||
}
|
||||
) {
|
||||
if (chatEvent is T) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val message = (this as ChatEventMessage<T>)
|
||||
if (filter == null) {
|
||||
if (mapper == null) {
|
||||
message.chatEvent
|
||||
} else {
|
||||
filter(message)
|
||||
mapper(message)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
@@ -55,124 +68,144 @@ suspend fun BehaviourContext.waitChannelEvents(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: EventMessageToEventMapper<ChannelEvent>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<ChatEventMessage<ChannelEvent>>? = null,
|
||||
mapper: EventMessageToEventMapper<ChannelEvent>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter, mapper)
|
||||
|
||||
suspend fun BehaviourContext.waitChatEvents(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: EventMessageToEventMapper<ChatEvent>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<ChatEventMessage<ChatEvent>>? = null,
|
||||
mapper: EventMessageToEventMapper<ChatEvent>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter, mapper)
|
||||
|
||||
suspend fun BehaviourContext.waitVoiceChatEvents(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: EventMessageToEventMapper<VoiceChatEvent>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<ChatEventMessage<VoiceChatEvent>>? = null,
|
||||
mapper: EventMessageToEventMapper<VoiceChatEvent>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitVoiceChatStartedEvents(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: EventMessageToEventMapper<VoiceChatStarted>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<ChatEventMessage<VoiceChatStarted>>? = null,
|
||||
mapper: EventMessageToEventMapper<VoiceChatStarted>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitVoiceChatEndedEvents(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: EventMessageToEventMapper<VoiceChatEnded>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<ChatEventMessage<VoiceChatEnded>>? = null,
|
||||
mapper: EventMessageToEventMapper<VoiceChatEnded>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitVoiceChatParticipantsInvitedEvents(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: EventMessageToEventMapper<VoiceChatParticipantsInvited>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<ChatEventMessage<VoiceChatParticipantsInvited>>? = null,
|
||||
mapper: EventMessageToEventMapper<VoiceChatParticipantsInvited>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter, mapper)
|
||||
|
||||
suspend fun BehaviourContext.waitMessageAutoDeleteTimerChangedEvents(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: EventMessageToEventMapper<MessageAutoDeleteTimerChanged>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<ChatEventMessage<MessageAutoDeleteTimerChanged>>? = null,
|
||||
mapper: EventMessageToEventMapper<MessageAutoDeleteTimerChanged>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter, mapper)
|
||||
|
||||
suspend fun BehaviourContext.waitCommonEvents(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: EventMessageToEventMapper<CommonEvent>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<ChatEventMessage<CommonEvent>>? = null,
|
||||
mapper: EventMessageToEventMapper<CommonEvent>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitGroupEvents(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: EventMessageToEventMapper<GroupEvent>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<ChatEventMessage<GroupEvent>>? = null,
|
||||
mapper: EventMessageToEventMapper<GroupEvent>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitSupergroupEvents(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: EventMessageToEventMapper<SupergroupEvent>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<ChatEventMessage<SupergroupEvent>>? = null,
|
||||
mapper: EventMessageToEventMapper<SupergroupEvent>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter, mapper)
|
||||
|
||||
suspend fun BehaviourContext.waitChannelChatCreatedEvents(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: EventMessageToEventMapper<ChannelChatCreated>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<ChatEventMessage<ChannelChatCreated>>? = null,
|
||||
mapper: EventMessageToEventMapper<ChannelChatCreated>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitDeleteChatPhotoEvents(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: EventMessageToEventMapper<DeleteChatPhoto>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<ChatEventMessage<DeleteChatPhoto>>? = null,
|
||||
mapper: EventMessageToEventMapper<DeleteChatPhoto>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitGroupChatCreatedEvents(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: EventMessageToEventMapper<GroupChatCreated>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<ChatEventMessage<GroupChatCreated>>? = null,
|
||||
mapper: EventMessageToEventMapper<GroupChatCreated>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitLeftChatMemberEvents(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: EventMessageToEventMapper<LeftChatMember>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<ChatEventMessage<LeftChatMember>>? = null,
|
||||
mapper: EventMessageToEventMapper<LeftChatMember>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitNewChatPhotoEvents(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: EventMessageToEventMapper<NewChatPhoto>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<ChatEventMessage<NewChatPhoto>>? = null,
|
||||
mapper: EventMessageToEventMapper<NewChatPhoto>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitNewChatMembersEvents(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: EventMessageToEventMapper<NewChatMembers>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<ChatEventMessage<NewChatMembers>>? = null,
|
||||
mapper: EventMessageToEventMapper<NewChatMembers>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitNewChatTitleEvents(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: EventMessageToEventMapper<NewChatTitle>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<ChatEventMessage<NewChatTitle>>? = null,
|
||||
mapper: EventMessageToEventMapper<NewChatTitle>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitPinnedMessageEvents(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: EventMessageToEventMapper<PinnedMessage>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<ChatEventMessage<PinnedMessage>>? = null,
|
||||
mapper: EventMessageToEventMapper<PinnedMessage>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitProximityAlertTriggeredEvents(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: EventMessageToEventMapper<ProximityAlertTriggered>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<ChatEventMessage<ProximityAlertTriggered>>? = null,
|
||||
mapper: EventMessageToEventMapper<ProximityAlertTriggered>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitSupergroupChatCreatedEvents(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: EventMessageToEventMapper<SupergroupChatCreated>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<ChatEventMessage<SupergroupChatCreated>>? = null,
|
||||
mapper: EventMessageToEventMapper<SupergroupChatCreated>? = null
|
||||
) = waitEvents(count, initRequest, errorFactory, filter, mapper)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations
|
||||
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter
|
||||
import dev.inmo.tgbotapi.extensions.utils.asInlineQueryUpdate
|
||||
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||
import dev.inmo.tgbotapi.types.InlineQueries.query.*
|
||||
@@ -12,13 +13,19 @@ private suspend fun <O> BehaviourContext.waitInlineQueries(
|
||||
count: Int = 1,
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
filter: SimpleFilter<InlineQuery>? = null,
|
||||
mapper: suspend InlineQuery.() -> O?
|
||||
): List<O> = expectFlow(
|
||||
initRequest,
|
||||
count,
|
||||
errorFactory
|
||||
) {
|
||||
it.asInlineQueryUpdate() ?.data ?.mapper().let(::listOfNotNull)
|
||||
val data = it.asInlineQueryUpdate() ?.data
|
||||
if (data != null && (filter == null || filter(data))) {
|
||||
data.mapper().let(::listOfNotNull)
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}.toList().toList()
|
||||
|
||||
|
||||
@@ -26,17 +33,23 @@ private suspend inline fun <reified T : InlineQuery> BehaviourContext.waitInline
|
||||
count: Int = 1,
|
||||
initRequest: Request<*>? = null,
|
||||
noinline errorFactory: NullableRequestBuilder<*> = { null },
|
||||
noinline filter: InlineQueryMapper<T>? = null
|
||||
noinline filter: SimpleFilter<T>? = null,
|
||||
noinline mapper: InlineQueryMapper<T>? = null
|
||||
) : List<T> = waitInlineQueries<T>(
|
||||
count,
|
||||
initRequest,
|
||||
errorFactory
|
||||
errorFactory,
|
||||
filter ?.let {
|
||||
{
|
||||
(it as? T) ?.let { casted -> filter(casted) } == true
|
||||
}
|
||||
}
|
||||
) {
|
||||
if (this is T) {
|
||||
if (filter == null) {
|
||||
if (mapper == null) {
|
||||
this
|
||||
} else {
|
||||
filter(this)
|
||||
mapper(this)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
@@ -47,18 +60,21 @@ suspend fun BehaviourContext.waitAnyInlineQuery(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: InlineQueryMapper<InlineQuery>? = null
|
||||
) = waitInlines(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<InlineQuery>? = null,
|
||||
mapper: InlineQueryMapper<InlineQuery>? = null
|
||||
) = waitInlines(count, initRequest, errorFactory, filter, mapper)
|
||||
|
||||
suspend fun BehaviourContext.waitBaseInlineQuery(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: InlineQueryMapper<BaseInlineQuery>? = null
|
||||
) = waitInlines(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<BaseInlineQuery>? = null,
|
||||
mapper: InlineQueryMapper<BaseInlineQuery>? = null
|
||||
) = waitInlines(count, initRequest, errorFactory, filter, mapper)
|
||||
suspend fun BehaviourContext.waitLocationInlineQuery(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: InlineQueryMapper<LocationInlineQuery>? = null
|
||||
) = waitInlines(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<LocationInlineQuery>? = null,
|
||||
mapper: InlineQueryMapper<LocationInlineQuery>? = null
|
||||
) = waitInlines(count, initRequest, errorFactory, filter, mapper)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations
|
||||
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter
|
||||
import dev.inmo.tgbotapi.extensions.utils.asMessageUpdate
|
||||
import dev.inmo.tgbotapi.extensions.utils.asPassportMessage
|
||||
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||
@@ -17,30 +18,38 @@ suspend fun <O> BehaviourContext.waitPassportMessages(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: SimpleFilter<PassportMessage>? = null,
|
||||
mapper: suspend PassportMessage.() -> O?
|
||||
): List<O> = expectFlow(
|
||||
initRequest,
|
||||
count,
|
||||
errorFactory
|
||||
) {
|
||||
it.asMessageUpdate() ?.data ?.asPassportMessage() ?.mapper().let(::listOfNotNull)
|
||||
val data = it.asMessageUpdate() ?.data ?.asPassportMessage() ?: return@expectFlow emptyList()
|
||||
if (filter == null || filter(data)) {
|
||||
data.mapper().let(::listOfNotNull)
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}.toList().toList()
|
||||
|
||||
suspend inline fun <reified T : EncryptedPassportElement> BehaviourContext.waitPassportMessagesWith(
|
||||
count: Int = 1,
|
||||
initRequest: Request<*>? = null,
|
||||
noinline errorFactory: NullableRequestBuilder<*> = { null },
|
||||
noinline filter: PassportMessageMapper? = null
|
||||
noinline filter: SimpleFilter<PassportMessage>? = null,
|
||||
noinline mapper: PassportMessageMapper? = null
|
||||
) : List<PassportData> = waitPassportMessages(
|
||||
initRequest,
|
||||
errorFactory,
|
||||
count
|
||||
count,
|
||||
filter
|
||||
) {
|
||||
if (passportData.data.any { it is T }) {
|
||||
if (filter == null) {
|
||||
if (mapper == null) {
|
||||
passportData
|
||||
} else {
|
||||
filter(this)
|
||||
mapper(this)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
@@ -51,5 +60,6 @@ suspend fun BehaviourContext.waitAnyPassportMessages(
|
||||
initRequest: Request<*>? = null,
|
||||
errorFactory: NullableRequestBuilder<*> = { null },
|
||||
count: Int = 1,
|
||||
filter: PassportMessageMapper? = null
|
||||
) = waitPassportMessagesWith<EncryptedPassportElement>(count, initRequest, errorFactory, filter)
|
||||
filter: SimpleFilter<PassportMessage>? = null,
|
||||
mapper: PassportMessageMapper? = null
|
||||
) = waitPassportMessagesWith<EncryptedPassportElement>(count, initRequest, errorFactory, filter, mapper)
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package dev.inmo.tgbotapi.extensions.behaviour_builder.filters
|
||||
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver
|
||||
import dev.inmo.tgbotapi.extensions.utils.extensions.sourceChat
|
||||
import dev.inmo.tgbotapi.types.CallbackQuery.CallbackQuery
|
||||
import dev.inmo.tgbotapi.types.ChatMemberUpdated
|
||||
import dev.inmo.tgbotapi.types.InlineQueries.query.InlineQuery
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.Message
|
||||
import dev.inmo.tgbotapi.types.update.abstracts.Update
|
||||
|
||||
/**
|
||||
* Allow only events from the same chat as base [Message]
|
||||
*/
|
||||
val MessageFilterByChat: BehaviourContextAndTwoTypesReceiver<Boolean, Message, Update> = { message, update ->
|
||||
update.sourceChat() ?.id == message.chat.id
|
||||
}
|
||||
/**
|
||||
* Allow only events from the same chat as base [List] of [Message]
|
||||
*/
|
||||
val MessagesFilterByChat: BehaviourContextAndTwoTypesReceiver<Boolean, List<Message>, Update> = { messages, update ->
|
||||
val sourceChatId = update.sourceChat() ?.id
|
||||
sourceChatId != null && messages.all { sourceChatId == it.chat.id }
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow only updates from the same user as base [CallbackQuery.user]
|
||||
*/
|
||||
val CallbackQueryFilterByUser: BehaviourContextAndTwoTypesReceiver<Boolean, CallbackQuery, Update> = { query, update ->
|
||||
update.sourceChat() ?.id == query.user.id
|
||||
}
|
||||
/**
|
||||
* Allow only updates from the same user as base [InlineQuery.from]
|
||||
*/
|
||||
val InlineQueryFilterByUser: BehaviourContextAndTwoTypesReceiver<Boolean, InlineQuery, Update> = { query, update ->
|
||||
update.sourceChat() ?.id == query.from.id
|
||||
}
|
||||
/**
|
||||
* Allow only events from the same chat as base [ChatMemberUpdated]
|
||||
*/
|
||||
val ChatMemberUpdatedFilterByChat: BehaviourContextAndTwoTypesReceiver<Boolean, ChatMemberUpdated, Update> = { updated, update ->
|
||||
update.sourceChat() ?.id == updated.chat.id
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user