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

Compare commits

..

69 Commits

Author SHA1 Message Date
3e5d939ea5 factory functions of BehaviourContextReceiver's, updates in kdocs and operations for these receivers filters 2021-09-21 21:36:52 +06:00
24f91e4aee Fix of #464 2021-09-21 20:50:59 +06:00
fe169fafaf add kdocs to LocationContent 2021-09-21 18:57:12 +06:00
aeb6fad409 add LocationContent#copy 2021-09-21 18:49:29 +06:00
94ad758814 deprecate old API in Behaviour Builder 2021-09-21 18:39:05 +06:00
5f01e26377 Update CHANGELOG.md 2021-09-21 16:24:12 +06:00
f82ac0ce9d Update gradle.properties 2021-09-21 16:23:47 +06:00
c8491765e9 update dependencies 2021-09-19 15:27:01 +06:00
53a3e11836 fix CustomBotAction annotations 2021-09-17 16:50:54 +06:00
fcccbe3252 Update CHANGELOG.md 2021-09-17 09:17:48 +06:00
584bf06109 Update gradle.properties 2021-09-17 09:17:28 +06:00
ef0083079e Update gradle.properties 2021-09-16 10:09:28 +06:00
0d01e9bc78 add kdocs for filters 2021-09-15 15:07:38 +06:00
89aef3d77b kdocs for triggers in behaviour builder 2021-09-15 14:58:45 +06:00
24c47b00d4 BehaviourContext#followLocation 2021-09-14 16:16:06 +06:00
a046a72392 waitEditedContent* extensions 2021-09-14 16:04:58 +06:00
a5a530c9bd TelegramBot#answer 2021-09-14 15:51:05 +06:00
9cf82a3564 subcontext filter and inBlock filter in behaviour context triggers 2021-09-13 23:30:01 +06:00
46cc37be62 LocationContent -> LiveLocationContent / StaticLocationContent 2021-09-12 17:15:58 +06:00
1fbaf396aa update micro_utils 2021-09-12 15:48:33 +06:00
76985501f5 CustomBotAction 2021-09-12 15:32:36 +06:00
8d8bcfba01 start 0.35.9 2021-09-12 15:29:19 +06:00
e0f3957249 Update CHANGELOG.md 2021-09-09 00:42:57 +06:00
3f1b018808 Merge pull request #457 from InsanusMokrassar/0.35.8
0.35.8
2021-09-08 22:43:23 +06:00
7af5ab17b7 Fixes in TelegramBot#withAction 2021-09-08 22:19:08 +06:00
0fec35f0dc BehaviourContext#commandWithArgs and BehaviourContext#onCommandWithArgs 2021-09-08 21:31:43 +06:00
ee81f49a75 add docs for InputFile 2021-09-08 21:13:42 +06:00
807952201b MPPFile#asMultipartFile 2021-09-08 20:58:44 +06:00
5d6ba0f59e MultipartRequestCallFactory improvements 2021-09-08 20:05:53 +06:00
3a61b522ab update dependencies 2021-09-08 19:59:29 +06:00
83304023a6 start 0.35.8 2021-09-08 19:57:22 +06:00
f62e13aaca Merge pull request #450 from InsanusMokrassar/0.35.7
0.35.7
2021-09-04 17:38:44 +06:00
ae1fb25336 update dependencies 2021-09-04 17:25:29 +06:00
4e3ea6cd80 fixes of annotations 2021-08-30 21:02:51 +06:00
148203eabf update klock 2021-08-30 18:55:13 +06:00
4465b573ca update dependencies 2021-08-27 19:58:21 +06:00
f0dda60630 start 0.35.7 2021-08-27 19:56:18 +06:00
47135a1b65 Merge pull request #444 from InsanusMokrassar/0.35.6
0.35.6
2021-08-23 22:26:56 +06:00
d8f830c60f FlowsUpdatesFilter update 2021-08-22 23:14:56 +06:00
226b8dee21 deprecate allSentMessagesFlow and allSentMedaGroupsFlow 2021-08-22 23:13:59 +06:00
a109771d20 update structure schema 2021-08-22 12:10:05 +06:00
c028434f30 update gradle wrapper 2021-08-22 11:09:35 +06:00
d5c6ce32bb fixes in readme :) 2021-08-22 11:02:14 +06:00
d92cac5e07 small updates in readmes 2021-08-22 10:59:01 +06:00
9b21b5290c update dokka 2021-08-22 10:53:12 +06:00
13ca63d27d update dependencies 2021-08-22 10:47:23 +06:00
ad917dda1b start 0.35.6 2021-08-22 10:35:55 +06:00
7b1344e9c8 Merge pull request #440 from InsanusMokrassar/0.35.5
0.35.5
2021-08-13 20:51:02 +06:00
c4fbd2f1c6 revert type of BuiltinMimeTypes 2021-08-13 18:39:46 +06:00
c90bcea42c add additional mime types 2021-08-13 18:39:08 +06:00
e75c93d626 remove mime types from requests 2021-08-13 14:02:39 +06:00
58dcbe8751 StorageFile#asMultipartFile 2021-08-13 11:45:36 +06:00
17806cde25 add calculation of mimed type from TelegramMediaFile when it is MimedFile 2021-08-13 11:43:36 +06:00
f147a3d620 fix of package for AdditionalContentAsStorageFile 2021-08-13 11:41:57 +06:00
9eb6008a73 convertToStorageFile 2021-08-13 11:37:01 +06:00
f7d2c8bbd2 hotfix 2021-08-10 16:54:15 +06:00
f42cf78969 fixes 2021-08-10 16:50:50 +06:00
9a14932511 small improvement of DownloadFileRequestCallFactory 2021-08-10 11:32:22 +06:00
149ecf175b small improvement of DownloadFileChannelRequestCallFactory 2021-08-10 11:29:46 +06:00
2049fea82a new asStorageFile 2021-08-10 11:08:08 +06:00
40d94cca70 improvements in files downloading api 2021-08-10 10:34:59 +06:00
c8ad68ea69 make ByteReadChannelAllocatorSerializer -> ByteReadChannelAllocatorDeserializationStrategy 2021-08-10 10:12:22 +06:00
c66d64adbc renames 2021-08-09 23:24:12 +06:00
b475976ff1 add streaming file downloading feature 2021-08-09 23:22:08 +06:00
ea8db5b851 rename JVM DownloadFile file 2021-08-09 20:01:26 +06:00
af2fabf1ca fix changelog 2021-08-09 19:55:51 +06:00
abc0457a36 files downloading improvements 2021-08-09 19:55:08 +06:00
8dbdbdee13 start 0.35.5 2021-08-09 19:39:03 +06:00
0c31379ff5 Merge pull request #439 from InsanusMokrassar/0.35.4
0.35.4
2021-08-09 14:18:19 +06:00
72 changed files with 4294 additions and 1840 deletions

View File

@@ -1,5 +1,82 @@
# 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`:

View File

@@ -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 | [![Awesome Kotlin Badge](https://kotlin.link/awesome-kotlin.svg)](https://github.com/KotlinBy/awesome-kotlin) [![Build Status](https://github.com/InsanusMokrassar/TelegramBotAPI/workflows/Build/badge.svg)](https://github.com/InsanusMokrassar/TelegramBotAPI/actions) [Small survey](https://forms.gle/2Hex2ynbHWHhi1KY7)|

1
TelegramBotAPI.drawio Normal file

File diff suppressed because one or more lines are too long

View File

@@ -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&#10;&#10;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&#10;&#10;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&#10;&#10;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&#10;&#10;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&#10;&#10;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&#10;&#10;Here included all available TelegramBotAPI libraries:&#13;&#10;&#13;&#10;* tgbotapi.core&#13;&#10;* tgbotapi.extensions.api&#13;&#10;* tgbotapi.extensions.utils&#10;* 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>

View File

@@ -1,3 +1,3 @@
dokka_version=1.4.32
dokka_version=1.5.30
org.gradle.jvmargs=-Xmx1024m

View File

@@ -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.19
micro_utils_version=0.5.28
javax_activation_version=1.1.1
library_group=dev.inmo
library_version=0.35.4
library_version=0.35.9
github_release_plugin_version=2.2.12

View File

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

View File

@@ -2,6 +2,20 @@
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.core)
- [TelegramBotAPI 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

View File

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

View File

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

View File

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

View File

@@ -24,8 +24,7 @@ class 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
)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -26,4 +26,6 @@ class TelegramAPIUrlsKeeper(
commonAPIUrl = "$correctedHost/bot$token"
fileBaseUrl = "$correctedHost/file/bot$token"
}
fun createFileLinkUrl(filePath: String) = "${fileBaseUrl}/$filePath"
}

View File

@@ -27,6 +27,7 @@ class BotActionTests {
FindLocationAction -> example.botAction.actionName
RecordVideoNoteAction -> example.botAction.actionName
UploadVideoNoteAction -> example.botAction.actionName
is CustomBotAction -> example.botAction.actionName
}
)
}

View File

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

View File

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

View File

@@ -0,0 +1,5 @@
package dev.inmo.tgbotapi.requests.abstracts
import dev.inmo.micro_utils.common.MPPFile
actual suspend fun MPPFile.asMultipartFile(): MultipartFile = toInputFile()

View File

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

View File

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

View File

@@ -1,8 +1,19 @@
# TelegramBotAPI extensions
[![Download](https://api.bintray.com/packages/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.api/images/download.svg) ](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.api/_latestVersion)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.api/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.api)
- [TelegramBotAPI 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

View File

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

View 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,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,16 @@
# TelegramBotAPI Behaviour Builder Extensions
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.behaviour_builder/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.behaviour_builder)
- [TelegramBotAPI 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

View File

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

View File

@@ -51,6 +51,22 @@ private suspend fun <O> BehaviourContext.waitCommonMessage(
}
}.toList().toList()
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 (mapper == null) {
message.content
} else {
safelyWithoutExceptions { mapper(message) }
}
} else {
null
}
}
private suspend inline fun <reified T : MessageContent> BehaviourContext.waitContent(
count: Int = 1,
initRequest: Request<*>? = null,
@@ -67,20 +83,9 @@ private suspend inline fun <reified T : MessageContent> BehaviourContext.waitCon
{
it.withContent<T>() ?.let { filter(it) } == true
}
}
) {
if (content is T) {
@Suppress("UNCHECKED_CAST")
val message = (this as CommonMessage<T>)
if (mapper == null) {
message.content
} else {
safelyWithoutExceptions { mapper(message) }
}
} else {
null
}
}
},
contentConverter(mapper)
)
suspend fun BehaviourContext.waitContentMessage(
initRequest: Request<*>? = null,
@@ -118,6 +123,20 @@ suspend fun BehaviourContext.waitLocation(
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 },

View File

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

View File

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

View File

@@ -0,0 +1,21 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder.filters
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.CommonMessageFilter
import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage
import dev.inmo.tgbotapi.types.message.abstracts.MediaGroupMessage
import dev.inmo.tgbotapi.types.update.abstracts.Update
/**
* Allow only messages which are not [MediaGroupMessage]
*/
val MessageFilterExcludingMediaGroups: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<*>, Update> = { message, update ->
update !is MediaGroupMessage<*>
}
/**
* Allow only messages which are not [MediaGroupMessage]
*/
val CommonMessageFilterExcludeMediaGroups: CommonMessageFilter<*> = {
it !is MediaGroupMessage<*>
}

View File

@@ -1,97 +1,346 @@
@file:Suppress("unused")
package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptionsAsync
import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.expectFlow
import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.CallbackQueryFilterByUser
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByUserCallbackQueryMarkerFactory
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory
import dev.inmo.tgbotapi.extensions.utils.asCallbackQueryUpdate
import dev.inmo.tgbotapi.extensions.utils.extensions.sourceChat
import dev.inmo.tgbotapi.types.CallbackQuery.*
import dev.inmo.tgbotapi.types.update.abstracts.Update
internal suspend inline fun <reified T : CallbackQuery> BehaviourContext.onCallbackQuery(
includeFilterByChatInBehaviourSubContext: Boolean = true,
noinline additionalFilter: SimpleFilter<T>? = null,
noinline initialFilter: SimpleFilter<T>? = null,
noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, T, Update>? = CallbackQueryFilterByUser,
markerFactory: MarkerFactory<in T, Any> = ByUserCallbackQueryMarkerFactory,
noinline scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, T>
) = flowsUpdatesFilter.expectFlow(bot) {
it.asCallbackQueryUpdate() ?.data ?.let { query ->
if (query is T) {
if (additionalFilter == null || additionalFilter(query)) query else null
} else {
null
}
}.let(::listOfNotNull)
}.subscribeSafelyWithoutExceptionsAsync(
scope,
markerFactory::invoke
) { triggerQuery ->
doInSubContextWithUpdatesFilter(
updatesFilter = if (includeFilterByChatInBehaviourSubContext) {
{ it.sourceChat() ?.id ?.chatId == triggerQuery.user.id.chatId }
} else {
null
},
stopOnCompletion = false
) {
scenarioReceiver(triggerQuery)
}
) = on(markerFactory, initialFilter, subcontextUpdatesFilter, scenarioReceiver) {
(it.asCallbackQueryUpdate() ?.data as? T) ?.let(::listOfNotNull)
}
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onDataCallbackQuery(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<DataCallbackQuery>? = null,
markerFactory: MarkerFactory<in DataCallbackQuery, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, DataCallbackQuery>
) = onCallbackQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onCallbackQuery(
additionalFilter,
if (includeFilterByChatInBehaviourSubContext) CallbackQueryFilterByUser else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onGameShortNameCallbackQuery(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<GameShortNameCallbackQuery>? = null,
markerFactory: MarkerFactory<in GameShortNameCallbackQuery, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, GameShortNameCallbackQuery>
) = onCallbackQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onCallbackQuery(
additionalFilter,
if (includeFilterByChatInBehaviourSubContext) CallbackQueryFilterByUser else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onInlineMessageIdCallbackQuery(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<InlineMessageIdCallbackQuery>? = null,
markerFactory: MarkerFactory<in InlineMessageIdCallbackQuery, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, InlineMessageIdCallbackQuery>
) = onCallbackQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onCallbackQuery(
additionalFilter,
if (includeFilterByChatInBehaviourSubContext) CallbackQueryFilterByUser else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onInlineMessageIdDataCallbackQuery(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<InlineMessageIdDataCallbackQuery>? = null,
markerFactory: MarkerFactory<in InlineMessageIdDataCallbackQuery, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, InlineMessageIdDataCallbackQuery>
) = onCallbackQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onCallbackQuery(
additionalFilter,
if (includeFilterByChatInBehaviourSubContext) CallbackQueryFilterByUser else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onInlineMessageIdGameShortNameCallbackQuery(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<InlineMessageIdGameShortNameCallbackQuery>? = null,
markerFactory: MarkerFactory<in InlineMessageIdGameShortNameCallbackQuery, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, InlineMessageIdGameShortNameCallbackQuery>
) = onCallbackQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onCallbackQuery(
additionalFilter,
if (includeFilterByChatInBehaviourSubContext) CallbackQueryFilterByUser else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onMessageCallbackQuery(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<MessageCallbackQuery>? = null,
markerFactory: MarkerFactory<in MessageCallbackQuery, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, MessageCallbackQuery>
) = onCallbackQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onCallbackQuery(
additionalFilter,
if (includeFilterByChatInBehaviourSubContext) CallbackQueryFilterByUser else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onMessageDataCallbackQuery(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<MessageDataCallbackQuery>? = null,
markerFactory: MarkerFactory<in MessageDataCallbackQuery, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, MessageDataCallbackQuery>
) = onCallbackQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onCallbackQuery(
additionalFilter,
if (includeFilterByChatInBehaviourSubContext) CallbackQueryFilterByUser else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onMessageGameShortNameCallbackQuery(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<MessageGameShortNameCallbackQuery>? = null,
markerFactory: MarkerFactory<in MessageGameShortNameCallbackQuery, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, MessageGameShortNameCallbackQuery>
) = onCallbackQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onCallbackQuery(
additionalFilter,
if (includeFilterByChatInBehaviourSubContext) CallbackQueryFilterByUser else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onUnknownCallbackQueryType(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<UnknownCallbackQueryType>? = null,
markerFactory: MarkerFactory<in UnknownCallbackQueryType, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, UnknownCallbackQueryType>
) = onCallbackQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onCallbackQuery(
additionalFilter,
if (includeFilterByChatInBehaviourSubContext) CallbackQueryFilterByUser else null,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onDataCallbackQuery(
initialFilter: SimpleFilter<DataCallbackQuery>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, DataCallbackQuery, Update>? = CallbackQueryFilterByUser,
markerFactory: MarkerFactory<in DataCallbackQuery, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, DataCallbackQuery>
) = onCallbackQuery(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onGameShortNameCallbackQuery(
initialFilter: SimpleFilter<GameShortNameCallbackQuery>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, GameShortNameCallbackQuery, Update>? = CallbackQueryFilterByUser,
markerFactory: MarkerFactory<in GameShortNameCallbackQuery, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, GameShortNameCallbackQuery>
) = onCallbackQuery(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onInlineMessageIdCallbackQuery(
initialFilter: SimpleFilter<InlineMessageIdCallbackQuery>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, InlineMessageIdCallbackQuery, Update>? = CallbackQueryFilterByUser,
markerFactory: MarkerFactory<in InlineMessageIdCallbackQuery, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, InlineMessageIdCallbackQuery>
) = onCallbackQuery(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onInlineMessageIdDataCallbackQuery(
initialFilter: SimpleFilter<InlineMessageIdDataCallbackQuery>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, InlineMessageIdDataCallbackQuery, Update>? = CallbackQueryFilterByUser,
markerFactory: MarkerFactory<in InlineMessageIdDataCallbackQuery, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, InlineMessageIdDataCallbackQuery>
) = onCallbackQuery(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onInlineMessageIdGameShortNameCallbackQuery(
initialFilter: SimpleFilter<InlineMessageIdGameShortNameCallbackQuery>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, InlineMessageIdGameShortNameCallbackQuery, Update>? = CallbackQueryFilterByUser,
markerFactory: MarkerFactory<in InlineMessageIdGameShortNameCallbackQuery, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, InlineMessageIdGameShortNameCallbackQuery>
) = onCallbackQuery(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onMessageCallbackQuery(
initialFilter: SimpleFilter<MessageCallbackQuery>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, MessageCallbackQuery, Update>? = CallbackQueryFilterByUser,
markerFactory: MarkerFactory<in MessageCallbackQuery, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, MessageCallbackQuery>
) = onCallbackQuery(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onMessageDataCallbackQuery(
initialFilter: SimpleFilter<MessageDataCallbackQuery>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, MessageDataCallbackQuery, Update>? = CallbackQueryFilterByUser,
markerFactory: MarkerFactory<in MessageDataCallbackQuery, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, MessageDataCallbackQuery>
) = onCallbackQuery(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onMessageGameShortNameCallbackQuery(
initialFilter: SimpleFilter<MessageGameShortNameCallbackQuery>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, MessageGameShortNameCallbackQuery, Update>? = CallbackQueryFilterByUser,
markerFactory: MarkerFactory<in MessageGameShortNameCallbackQuery, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, MessageGameShortNameCallbackQuery>
) = onCallbackQuery(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onUnknownCallbackQueryType(
initialFilter: SimpleFilter<UnknownCallbackQueryType>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, UnknownCallbackQueryType, Update>? = CallbackQueryFilterByUser,
markerFactory: MarkerFactory<in UnknownCallbackQueryType, Any> = ByUserCallbackQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, UnknownCallbackQueryType>
) = onCallbackQuery(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)

View File

@@ -1,74 +1,135 @@
@file:Suppress("unused")
package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling
import dev.inmo.micro_utils.coroutines.subscribeSafelySkippingExceptionsAsync
import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.expectFlow
import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.ChatMemberUpdatedFilterByChat
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByChatChatMemberUpdatedMarkerFactory
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory
import dev.inmo.tgbotapi.extensions.utils.extensions.sourceChat
import dev.inmo.tgbotapi.types.ChatMemberUpdated
import dev.inmo.tgbotapi.types.update.CommonChatMemberUpdatedUpdate
import dev.inmo.tgbotapi.types.update.MyChatMemberUpdatedUpdate
import dev.inmo.tgbotapi.types.update.abstracts.ChatMemberUpdatedUpdate
import dev.inmo.tgbotapi.types.update.abstracts.Update
internal suspend inline fun <reified U : ChatMemberUpdatedUpdate> BehaviourContext.onChatMemberUpdatedInternal(
includeFilterByChatInBehaviourSubContext: Boolean = true,
noinline additionalFilter: SimpleFilter<ChatMemberUpdated>? = null,
noinline initialFilter: SimpleFilter<ChatMemberUpdated>? = null,
noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatMemberUpdated, Update>? = ChatMemberUpdatedFilterByChat,
markerFactory: MarkerFactory<ChatMemberUpdated, Any> = ByChatChatMemberUpdatedMarkerFactory,
noinline scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatMemberUpdated>
) = flowsUpdatesFilter.expectFlow(bot) {
(it as? U) ?.data ?.let { chatMemberUpdated ->
if (additionalFilter == null || additionalFilter(chatMemberUpdated)) chatMemberUpdated else null
}.let(::listOfNotNull)
}.subscribeSafelySkippingExceptionsAsync(
scope,
markerFactory::invoke
) { triggerChatMemberUpdated ->
doInSubContextWithUpdatesFilter(
updatesFilter = if (includeFilterByChatInBehaviourSubContext) {
{ it.sourceChat() ?.id ?.chatId == triggerChatMemberUpdated.chat.id.chatId }
} else {
null
},
stopOnCompletion = false
) {
scenarioReceiver(triggerChatMemberUpdated)
}
) = on(markerFactory, initialFilter, subcontextUpdatesFilter, scenarioReceiver) {
((it as? U) ?.data) ?.let(::listOfNotNull)
}
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onChatMemberUpdated(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<ChatMemberUpdated>? = null,
markerFactory: MarkerFactory<ChatMemberUpdated, Any> = ByChatChatMemberUpdatedMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatMemberUpdated>
) = onChatMemberUpdatedInternal<ChatMemberUpdatedUpdate>(
includeFilterByChatInBehaviourSubContext,
additionalFilter,
if (includeFilterByChatInBehaviourSubContext) ChatMemberUpdatedFilterByChat else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onCommonChatMemberUpdated(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<ChatMemberUpdated>? = null,
markerFactory: MarkerFactory<ChatMemberUpdated, Any> = ByChatChatMemberUpdatedMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatMemberUpdated>
) = onChatMemberUpdatedInternal<CommonChatMemberUpdatedUpdate>(
includeFilterByChatInBehaviourSubContext,
additionalFilter,
if (includeFilterByChatInBehaviourSubContext) ChatMemberUpdatedFilterByChat else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onMyChatMemberUpdated(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<ChatMemberUpdated>? = null,
markerFactory: MarkerFactory<ChatMemberUpdated, Any> = ByChatChatMemberUpdatedMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatMemberUpdated>
) = onChatMemberUpdatedInternal<MyChatMemberUpdatedUpdate>(
includeFilterByChatInBehaviourSubContext,
additionalFilter,
if (includeFilterByChatInBehaviourSubContext) ChatMemberUpdatedFilterByChat else null,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onChatMemberUpdated(
initialFilter: SimpleFilter<ChatMemberUpdated>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatMemberUpdated, Update>? = ChatMemberUpdatedFilterByChat,
markerFactory: MarkerFactory<ChatMemberUpdated, Any> = ByChatChatMemberUpdatedMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatMemberUpdated>
) = onChatMemberUpdatedInternal<ChatMemberUpdatedUpdate>(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onCommonChatMemberUpdated(
initialFilter: SimpleFilter<ChatMemberUpdated>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatMemberUpdated, Update>? = ChatMemberUpdatedFilterByChat,
markerFactory: MarkerFactory<ChatMemberUpdated, Any> = ByChatChatMemberUpdatedMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatMemberUpdated>
) = onChatMemberUpdatedInternal<CommonChatMemberUpdatedUpdate>(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onMyChatMemberUpdated(
initialFilter: SimpleFilter<ChatMemberUpdated>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatMemberUpdated, Update>? = ChatMemberUpdatedFilterByChat,
markerFactory: MarkerFactory<ChatMemberUpdated, Any> = ByChatChatMemberUpdatedMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatMemberUpdated>
) = onChatMemberUpdatedInternal<MyChatMemberUpdatedUpdate>(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)

View File

@@ -1,24 +1,31 @@
@file:Suppress("unused")
package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTypeReceiver
import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.CommonMessageFilterExcludeMediaGroups
import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.MessageFilterByChat
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByChatMessageMarkerFactory
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times
import dev.inmo.tgbotapi.extensions.utils.asBotCommandTextSource
import dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithParams
import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage
import dev.inmo.tgbotapi.types.message.content.TextContent
import dev.inmo.tgbotapi.types.update.abstracts.Update
import kotlinx.coroutines.Job
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.command(
commandRegex: Regex,
requireOnlyCommandInMessage: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: CommonMessageFilter<TextContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<TextContent>>
): Job = onText(
includeFilterByChatInBehaviourSubContext,
{ message ->
CommonMessageFilter<TextContent> { message ->
val content = message.content
val textSources = content.textSources
val sizeRequirement = if (requireOnlyCommandInMessage) {
@@ -29,33 +36,198 @@ suspend fun BehaviourContext.command(
sizeRequirement && textSources.any {
commandRegex.matches(it.asBotCommandTextSource() ?.command ?: return@any false)
} && (additionalFilter ?.invoke(message) != false)
}.let {
additionalFilter ?.times(it) ?: it
},
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.command(
command: String,
requireOnlyCommandInMessage: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: CommonMessageFilter<TextContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<TextContent>>
) = command(command.toRegex(), requireOnlyCommandInMessage, includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend inline fun BehaviourContext.onCommand(
commandRegex: Regex,
requireOnlyCommandInMessage: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
noinline additionalFilter: CommonMessageFilter<TextContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
noinline scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<TextContent>>
): Job = command(commandRegex, requireOnlyCommandInMessage, includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend inline fun BehaviourContext.onCommand(
command: String,
requireOnlyCommandInMessage: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
noinline additionalFilter: CommonMessageFilter<TextContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
noinline scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<TextContent>>
): Job = onCommand(command.toRegex(), requireOnlyCommandInMessage, includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.commandWithArgs(
commandRegex: Regex,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: CommonMessageFilter<TextContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTwoTypesReceiver<Unit, CommonMessage<TextContent>, Array<String>>
) = command(
commandRegex,
requireOnlyCommandInMessage = false,
includeFilterByChatInBehaviourSubContext = includeFilterByChatInBehaviourSubContext,
additionalFilter = additionalFilter,
markerFactory = markerFactory
) {
val args = it.parseCommandsWithParams().let { commandsWithArgs ->
val key = commandsWithArgs.keys.firstOrNull { it.matches(commandRegex) } ?: return@let null
commandsWithArgs[key]
} ?: emptyArray()
scenarioReceiver(it, args)
}
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.commandWithArgs(
command: String,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: CommonMessageFilter<TextContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTwoTypesReceiver<Unit, CommonMessage<TextContent>, Array<String>>
) = commandWithArgs(
command.toRegex(),
includeFilterByChatInBehaviourSubContext = includeFilterByChatInBehaviourSubContext,
additionalFilter = additionalFilter,
markerFactory = markerFactory,
scenarioReceiver = scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend inline fun BehaviourContext.onCommandWithArgs(
commandRegex: Regex,
includeFilterByChatInBehaviourSubContext: Boolean,
noinline additionalFilter: CommonMessageFilter<TextContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
noinline scenarioReceiver: BehaviourContextAndTwoTypesReceiver<Unit, CommonMessage<TextContent>, Array<String>>
): Job = commandWithArgs(commandRegex, includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend inline fun BehaviourContext.onCommandWithArgs(
command: String,
includeFilterByChatInBehaviourSubContext: Boolean,
noinline additionalFilter: CommonMessageFilter<TextContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
noinline scenarioReceiver: BehaviourContextAndTwoTypesReceiver<Unit, CommonMessage<TextContent>, Array<String>>
): Job = onCommandWithArgs(command.toRegex(), includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
suspend fun BehaviourContext.command(
commandRegex: Regex,
requireOnlyCommandInMessage: Boolean = true,
initialFilter: CommonMessageFilter<TextContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<TextContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<TextContent>>
): Job = onText(
CommonMessageFilter<TextContent> { message ->
val content = message.content
val textSources = content.textSources
val sizeRequirement = if (requireOnlyCommandInMessage) {
textSources.size == 1
} else {
true
}
sizeRequirement && textSources.any {
commandRegex.matches(it.asBotCommandTextSource() ?.command ?: return@any false)
}
}.let {
initialFilter ?.times(it) ?: it
},
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
suspend fun BehaviourContext.command(
command: String,
requireOnlyCommandInMessage: Boolean = true,
initialFilter: CommonMessageFilter<TextContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<TextContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<TextContent>>
) = command(command.toRegex(), requireOnlyCommandInMessage, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend inline fun BehaviourContext.onCommand(
commandRegex: Regex,
requireOnlyCommandInMessage: Boolean = true,
noinline initialFilter: CommonMessageFilter<TextContent>? = CommonMessageFilterExcludeMediaGroups,
noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<TextContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
noinline scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<TextContent>>
): Job = command(commandRegex, requireOnlyCommandInMessage, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend inline fun BehaviourContext.onCommand(
command: String,
requireOnlyCommandInMessage: Boolean = true,
noinline initialFilter: CommonMessageFilter<TextContent>? = CommonMessageFilterExcludeMediaGroups,
noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<TextContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
noinline scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<TextContent>>
): Job = onCommand(command.toRegex(), requireOnlyCommandInMessage, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend fun BehaviourContext.commandWithArgs(
commandRegex: Regex,
initialFilter: CommonMessageFilter<TextContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<TextContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTwoTypesReceiver<Unit, CommonMessage<TextContent>, Array<String>>
) = command(
commandRegex,
requireOnlyCommandInMessage = false,
initialFilter = initialFilter,
subcontextUpdatesFilter = subcontextUpdatesFilter,
markerFactory = markerFactory
) {
val args = it.parseCommandsWithParams().let { commandsWithArgs ->
val key = commandsWithArgs.keys.firstOrNull { it.matches(commandRegex) } ?: return@let null
commandsWithArgs[key]
} ?: emptyArray()
scenarioReceiver(it, args)
}
suspend fun BehaviourContext.commandWithArgs(
command: String,
initialFilter: CommonMessageFilter<TextContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<TextContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTwoTypesReceiver<Unit, CommonMessage<TextContent>, Array<String>>
) = commandWithArgs(
command.toRegex(),
initialFilter = initialFilter,
subcontextUpdatesFilter = subcontextUpdatesFilter,
markerFactory = markerFactory,
scenarioReceiver = scenarioReceiver
)
suspend inline fun BehaviourContext.onCommandWithArgs(
commandRegex: Regex,
noinline initialFilter: CommonMessageFilter<TextContent>? = CommonMessageFilterExcludeMediaGroups,
noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<TextContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
noinline scenarioReceiver: BehaviourContextAndTwoTypesReceiver<Unit, CommonMessage<TextContent>, Array<String>>
): Job = commandWithArgs(commandRegex, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
suspend inline fun BehaviourContext.onCommandWithArgs(
command: String,
noinline initialFilter: CommonMessageFilter<TextContent>? = CommonMessageFilterExcludeMediaGroups,
noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<TextContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
noinline scenarioReceiver: BehaviourContextAndTwoTypesReceiver<Unit, CommonMessage<TextContent>, Array<String>>
): Job = onCommandWithArgs(command.toRegex(), initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)

View File

@@ -2,194 +2,851 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptionsAsync
import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.expectFlow
import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.CommonMessageFilterExcludeMediaGroups
import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.MessageFilterByChat
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByChatMessageMarkerFactory
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory
import dev.inmo.tgbotapi.extensions.utils.*
import dev.inmo.tgbotapi.extensions.utils.extensions.sourceChat
import dev.inmo.tgbotapi.extensions.utils.whenCommonMessage
import dev.inmo.tgbotapi.types.files.abstracts.TelegramMediaFile
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.utils.PreviewFeature
import dev.inmo.tgbotapi.types.update.MediaGroupUpdates.SentMediaGroupUpdate
import dev.inmo.tgbotapi.types.update.abstracts.BaseSentMessageUpdate
import dev.inmo.tgbotapi.types.update.abstracts.Update
typealias CommonMessageFilter<T> = SimpleFilter<CommonMessage<T>>
inline fun <T : MessageContent> CommonMessageFilter(noinline block: CommonMessageFilter<T>) = block
@PreviewFeature
internal suspend inline fun <reified T : MessageContent> BehaviourContext.onContent(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeMediaGroups: Boolean = true,
noinline additionalFilter: CommonMessageFilter<T>? = null,
noinline initialFilter: CommonMessageFilter<T>? = null,
noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<T>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<T>, Any> = ByChatMessageMarkerFactory,
noinline scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<T>>
) = flowsUpdatesFilter.expectFlow(bot) {
val messages = it.whenBaseSentMessageUpdate {
it.data.whenCommonMessage(::listOfNotNull)
} ?: if (includeMediaGroups) {
it.asSentMediaGroupUpdate() ?.data ?: emptyList()
} else {
emptyList()
}
messages.mapNotNull { message ->
if (message.content is T) {
val adaptedMessage = message as CommonMessage<T>
if (additionalFilter == null || additionalFilter(adaptedMessage)) adaptedMessage else null
} else {
null
}
}
}.subscribeSafelyWithoutExceptionsAsync(
scope,
markerFactory::invoke
) { triggerMessage ->
doInSubContextWithUpdatesFilter(
updatesFilter = if (includeFilterByChatInBehaviourSubContext) {
{ it.sourceChat() ?.id ?.chatId == triggerMessage.chat.id.chatId }
} else {
null
},
stopOnCompletion = false
) {
scenarioReceiver(triggerMessage)
) = on(markerFactory, initialFilter, subcontextUpdatesFilter, scenarioReceiver) {
when (it) {
is BaseSentMessageUpdate -> it.data.whenCommonMessage(::listOfNotNull)
is SentMediaGroupUpdate -> it.data
else -> null
} ?.mapNotNull { message ->
if (message.content is T) message as CommonMessage<T> else null
}
}
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onContentMessage(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: CommonMessageFilter<MessageContent>? = null,
includeMediaGroups: Boolean = true,
markerFactory: MarkerFactory<in CommonMessage<MessageContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<MessageContent>>
) = onContent(includeFilterByChatInBehaviourSubContext, includeMediaGroups, additionalFilter, markerFactory, scenarioReceiver)
) = onContent(
additionalFilter ?: if (includeMediaGroups) null else CommonMessageFilterExcludeMediaGroups,
if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onContact(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: CommonMessageFilter<ContactContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<ContactContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<ContactContent>>
) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver)
) = onContent(
additionalFilter ?: CommonMessageFilterExcludeMediaGroups,
if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onDice(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: CommonMessageFilter<DiceContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<DiceContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<DiceContent>>
) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver)
) = onContent(
additionalFilter ?: CommonMessageFilterExcludeMediaGroups,
if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onGame(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: CommonMessageFilter<GameContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<GameContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<GameContent>>
) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver)
) = onContent(
additionalFilter ?: CommonMessageFilterExcludeMediaGroups,
if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onLocation(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: CommonMessageFilter<LocationContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<LocationContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<LocationContent>>
) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver)
) = onContent(
additionalFilter ?: CommonMessageFilterExcludeMediaGroups,
if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onPoll(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: CommonMessageFilter<PollContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<PollContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<PollContent>>
) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver)
) = onContent(
additionalFilter ?: CommonMessageFilterExcludeMediaGroups,
if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onText(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: CommonMessageFilter<TextContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<TextContent>>
) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver)
) = onContent(
additionalFilter ?: CommonMessageFilterExcludeMediaGroups,
if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onVenue(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: CommonMessageFilter<VenueContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<VenueContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<VenueContent>>
) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver)
) = onContent(
additionalFilter ?: CommonMessageFilterExcludeMediaGroups,
if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onAudioMediaGroup(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: CommonMessageFilter<AudioMediaGroupContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<AudioMediaGroupContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<AudioMediaGroupContent>>
) = onContent(includeFilterByChatInBehaviourSubContext, true, additionalFilter, markerFactory, scenarioReceiver)
) = onContent(
additionalFilter,
if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onDocumentMediaGroupContent(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
includeMediaGroups: Boolean = true,
additionalFilter: CommonMessageFilter<DocumentMediaGroupContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<DocumentMediaGroupContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<DocumentMediaGroupContent>>
) = onContent(includeFilterByChatInBehaviourSubContext, includeMediaGroups, additionalFilter, markerFactory, scenarioReceiver)
) = onContent(
additionalFilter ?: if (includeMediaGroups) null else CommonMessageFilterExcludeMediaGroups,
if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onMediaCollection(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
includeMediaGroups: Boolean = false,
additionalFilter: SimpleFilter<CommonMessage<MediaCollectionContent<TelegramMediaFile>>>? = null,
markerFactory: MarkerFactory<in CommonMessage<MediaCollectionContent<TelegramMediaFile>>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<MediaCollectionContent<TelegramMediaFile>>>
) = onContent(includeFilterByChatInBehaviourSubContext, includeMediaGroups, additionalFilter, markerFactory, scenarioReceiver)
) = onContent(
additionalFilter ?: if (includeMediaGroups) null else CommonMessageFilterExcludeMediaGroups,
if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onMedia(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
includeMediaGroups: Boolean = true,
additionalFilter: CommonMessageFilter<MediaContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<MediaContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<MediaContent>>
) = onContent(includeFilterByChatInBehaviourSubContext, includeMediaGroups, additionalFilter, markerFactory, scenarioReceiver)
) = onContent(
additionalFilter ?: if (includeMediaGroups) null else CommonMessageFilterExcludeMediaGroups,
if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onAnimation(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: CommonMessageFilter<AnimationContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<AnimationContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<AnimationContent>>
) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver)
) = onContent(
additionalFilter ?: CommonMessageFilterExcludeMediaGroups,
if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onAudio(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
includeMediaGroups: Boolean = false,
additionalFilter: CommonMessageFilter<AudioContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<AudioContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<AudioContent>>
) = onContent(includeFilterByChatInBehaviourSubContext, includeMediaGroups, additionalFilter, markerFactory, scenarioReceiver)
) = onContent(
additionalFilter ?: if (includeMediaGroups) null else CommonMessageFilterExcludeMediaGroups,
if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onDocument(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
includeMediaGroups: Boolean = false,
additionalFilter: CommonMessageFilter<DocumentContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<DocumentContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<DocumentContent>>
) = onContent(includeFilterByChatInBehaviourSubContext, includeMediaGroups, additionalFilter, markerFactory, scenarioReceiver)
) = onContent(
additionalFilter ?: if (includeMediaGroups) null else CommonMessageFilterExcludeMediaGroups,
if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onPhoto(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
includeMediaGroups: Boolean = false,
additionalFilter: CommonMessageFilter<PhotoContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<PhotoContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<PhotoContent>>
) = onContent(includeFilterByChatInBehaviourSubContext, includeMediaGroups, additionalFilter, markerFactory, scenarioReceiver)
) = onContent(
additionalFilter ?: if (includeMediaGroups) null else CommonMessageFilterExcludeMediaGroups,
if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onSticker(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: CommonMessageFilter<StickerContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<StickerContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<StickerContent>>
) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver)
) = onContent(
additionalFilter ?: CommonMessageFilterExcludeMediaGroups,
if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onVideo(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
includeMediaGroups: Boolean = false,
additionalFilter: CommonMessageFilter<VideoContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<VideoContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<VideoContent>>
) = onContent(includeFilterByChatInBehaviourSubContext, includeMediaGroups, additionalFilter, markerFactory, scenarioReceiver)
) = onContent(
additionalFilter ?: if (includeMediaGroups) null else CommonMessageFilterExcludeMediaGroups,
if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onVideoNote(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: CommonMessageFilter<VideoNoteContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<VideoNoteContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<VideoNoteContent>>
) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver)
) = onContent(
additionalFilter ?: CommonMessageFilterExcludeMediaGroups,
if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onVoice(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: CommonMessageFilter<VoiceContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<VoiceContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<VoiceContent>>
) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver)
) = onContent(
additionalFilter ?: CommonMessageFilterExcludeMediaGroups,
if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null,
markerFactory,
scenarioReceiver
)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onInvoice(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: CommonMessageFilter<InvoiceContent>? = null,
markerFactory: MarkerFactory<in CommonMessage<InvoiceContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<InvoiceContent>>
) = onContent(includeFilterByChatInBehaviourSubContext, false, additionalFilter, markerFactory, scenarioReceiver)
) = onContent(
additionalFilter ?: CommonMessageFilterExcludeMediaGroups,
if (includeFilterByChatInBehaviourSubContext) { MessageFilterByChat } else null,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onContentMessage(
initialFilter: CommonMessageFilter<MessageContent>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<MessageContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<MessageContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<MessageContent>>
) = onContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onContact(
initialFilter: CommonMessageFilter<ContactContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<ContactContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<ContactContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<ContactContent>>
) = onContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onDice(
initialFilter: CommonMessageFilter<DiceContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<DiceContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<DiceContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<DiceContent>>
) = onContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onGame(
initialFilter: CommonMessageFilter<GameContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<GameContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<GameContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<GameContent>>
) = onContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onLocation(
initialFilter: CommonMessageFilter<LocationContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<LocationContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<LocationContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<LocationContent>>
) = onContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onLiveLocation(
initialFilter: CommonMessageFilter<LiveLocationContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<LiveLocationContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<LiveLocationContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<LiveLocationContent>>
) = onContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onStaticLocation(
initialFilter: CommonMessageFilter<StaticLocationContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<StaticLocationContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<StaticLocationContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<StaticLocationContent>>
) = onContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onPoll(
initialFilter: CommonMessageFilter<PollContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<PollContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<PollContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<PollContent>>
) = onContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onText(
initialFilter: CommonMessageFilter<TextContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<TextContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<TextContent>>
) = onContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onVenue(
initialFilter: CommonMessageFilter<VenueContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<VenueContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<VenueContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<VenueContent>>
) = onContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onAudioMediaGroup(
initialFilter: CommonMessageFilter<AudioMediaGroupContent>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<AudioMediaGroupContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<AudioMediaGroupContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<AudioMediaGroupContent>>
) = onContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onDocumentMediaGroupContent(
initialFilter: CommonMessageFilter<DocumentMediaGroupContent>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<DocumentMediaGroupContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<DocumentMediaGroupContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<DocumentMediaGroupContent>>
) = onContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onMediaCollection(
initialFilter: CommonMessageFilter<MediaCollectionContent<TelegramMediaFile>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<MediaCollectionContent<TelegramMediaFile>>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<MediaCollectionContent<TelegramMediaFile>>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<MediaCollectionContent<TelegramMediaFile>>>
) = onContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onMedia(
initialFilter: CommonMessageFilter<MediaContent>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<MediaContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<MediaContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<MediaContent>>
) = onContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onAnimation(
initialFilter: CommonMessageFilter<AnimationContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<AnimationContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<AnimationContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<AnimationContent>>
) = onContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onAudio(
initialFilter: CommonMessageFilter<AudioContent>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<AudioContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<AudioContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<AudioContent>>
) = onContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onDocument(
initialFilter: CommonMessageFilter<DocumentContent>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<DocumentContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<DocumentContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<DocumentContent>>
) = onContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onPhoto(
initialFilter: CommonMessageFilter<PhotoContent>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<PhotoContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<PhotoContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<PhotoContent>>
) = onContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onSticker(
initialFilter: CommonMessageFilter<StickerContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<StickerContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<StickerContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<StickerContent>>
) = onContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onVideo(
initialFilter: CommonMessageFilter<VideoContent>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<VideoContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<VideoContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<VideoContent>>
) = onContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onVideoNote(
initialFilter: CommonMessageFilter<VideoNoteContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<VideoNoteContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<VideoNoteContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<VideoNoteContent>>
) = onContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onVoice(
initialFilter: CommonMessageFilter<VoiceContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<VoiceContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<VoiceContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<VoiceContent>>
) = onContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onInvoice(
initialFilter: CommonMessageFilter<InvoiceContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<InvoiceContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<InvoiceContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<InvoiceContent>>
) = onContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)

View File

@@ -0,0 +1,551 @@
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/@file:Suppress("unused", "UNCHECKED_CAST")
package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling
import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.CommonMessageFilterExcludeMediaGroups
import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.MessageFilterByChat
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByChatMessageMarkerFactory
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory
import dev.inmo.tgbotapi.extensions.utils.asEditMessageUpdate
import dev.inmo.tgbotapi.extensions.utils.withContent
import dev.inmo.tgbotapi.types.files.abstracts.TelegramMediaFile
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.abstracts.BaseEditMessageUpdate
import dev.inmo.tgbotapi.types.update.abstracts.Update
import dev.inmo.tgbotapi.utils.PreviewFeature
@PreviewFeature
internal suspend inline fun <reified T : MessageContent> BehaviourContext.onEditedContent(
noinline initialFilter: CommonMessageFilter<T>? = null,
noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<T>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<T>, Any> = ByChatMessageMarkerFactory,
noinline scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<T>>
) = on(markerFactory, initialFilter, subcontextUpdatesFilter, scenarioReceiver) {
when (it) {
is BaseEditMessageUpdate -> (it.asEditMessageUpdate() ?.data ?.withContent<T>())
else -> null
} ?.let(::listOfNotNull)
}
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onEditedContentMessage(
initialFilter: CommonMessageFilter<MessageContent>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<MessageContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<MessageContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<MessageContent>>
)= onEditedContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onEditedContact(
initialFilter: CommonMessageFilter<ContactContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<ContactContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<ContactContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<ContactContent>>
)= onEditedContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onEditedDice(
initialFilter: CommonMessageFilter<DiceContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<DiceContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<DiceContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<DiceContent>>
)= onEditedContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onEditedGame(
initialFilter: CommonMessageFilter<GameContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<GameContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<GameContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<GameContent>>
)= onEditedContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onEditedLocation(
initialFilter: CommonMessageFilter<LocationContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<LocationContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<LocationContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<LocationContent>>
)= onEditedContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onEditedPoll(
initialFilter: CommonMessageFilter<PollContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<PollContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<PollContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<PollContent>>
)= onEditedContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onEditedText(
initialFilter: CommonMessageFilter<TextContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<TextContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<TextContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<TextContent>>
)= onEditedContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onEditedVenue(
initialFilter: CommonMessageFilter<VenueContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<VenueContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<VenueContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<VenueContent>>
)= onEditedContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onEditedAudioMediaGroup(
initialFilter: CommonMessageFilter<AudioMediaGroupContent>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<AudioMediaGroupContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<AudioMediaGroupContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<AudioMediaGroupContent>>
)= onEditedContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onEditedDocumentMediaGroupContent(
initialFilter: CommonMessageFilter<DocumentMediaGroupContent>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<DocumentMediaGroupContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<DocumentMediaGroupContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<DocumentMediaGroupContent>>
)= onEditedContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onEditedMediaCollection(
initialFilter: CommonMessageFilter<MediaCollectionContent<TelegramMediaFile>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<MediaCollectionContent<TelegramMediaFile>>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<MediaCollectionContent<TelegramMediaFile>>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<MediaCollectionContent<TelegramMediaFile>>>
)= onEditedContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onEditedMedia(
initialFilter: CommonMessageFilter<MediaContent>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<MediaContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<MediaContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<MediaContent>>
)= onEditedContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onEditedAnimation(
initialFilter: CommonMessageFilter<AnimationContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<AnimationContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<AnimationContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<AnimationContent>>
)= onEditedContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onEditedAudio(
initialFilter: CommonMessageFilter<AudioContent>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<AudioContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<AudioContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<AudioContent>>
)= onEditedContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onEditedDocument(
initialFilter: CommonMessageFilter<DocumentContent>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<DocumentContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<DocumentContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<DocumentContent>>
)= onEditedContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onEditedPhoto(
initialFilter: CommonMessageFilter<PhotoContent>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<PhotoContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<PhotoContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<PhotoContent>>
)= onEditedContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onEditedSticker(
initialFilter: CommonMessageFilter<StickerContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<StickerContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<StickerContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<StickerContent>>
)= onEditedContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onEditedVideo(
initialFilter: CommonMessageFilter<VideoContent>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<VideoContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<VideoContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<VideoContent>>
)= onEditedContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onEditedVideoNote(
initialFilter: CommonMessageFilter<VideoNoteContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<VideoNoteContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<VideoNoteContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<VideoNoteContent>>
)= onEditedContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onEditedVoice(
initialFilter: CommonMessageFilter<VoiceContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<VoiceContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<VoiceContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<VoiceContent>>
)= onEditedContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onEditedInvoice(
initialFilter: CommonMessageFilter<InvoiceContent>? = CommonMessageFilterExcludeMediaGroups,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, CommonMessage<InvoiceContent>, Update> = MessageFilterByChat,
markerFactory: MarkerFactory<in CommonMessage<InvoiceContent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, CommonMessage<InvoiceContent>>
)= onEditedContent(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)

View File

@@ -1,166 +1,549 @@
@file:Suppress("unused")
package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptionsAsync
import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.expectFlow
import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.MessageFilterByChat
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByChatMessageMarkerFactory
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory
import dev.inmo.tgbotapi.extensions.utils.asBaseSentMessageUpdate
import dev.inmo.tgbotapi.extensions.utils.asChatEventMessage
import dev.inmo.tgbotapi.extensions.utils.extensions.sourceChat
import dev.inmo.tgbotapi.types.message.ChatEvents.*
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.*
import dev.inmo.tgbotapi.types.message.ChatEvents.voice.*
import dev.inmo.tgbotapi.types.message.abstracts.ChatEventMessage
import dev.inmo.tgbotapi.types.update.abstracts.Update
internal suspend inline fun <reified T : ChatEvent> BehaviourContext.onEvent(
includeFilterByChatInBehaviourSubContext: Boolean = true,
noinline additionalFilter: SimpleFilter<ChatEventMessage<T>>? = null,
noinline initialFilter: SimpleFilter<ChatEventMessage<T>>? = null,
noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatEventMessage<T>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<T>, Any> = ByChatMessageMarkerFactory,
noinline scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<T>>
) = flowsUpdatesFilter.expectFlow(bot) {
it.asBaseSentMessageUpdate() ?.data ?.asChatEventMessage() ?.let { message ->
if (message.chatEvent is T) {
val adaptedMessage = message as ChatEventMessage<T>
if (additionalFilter == null || additionalFilter(adaptedMessage)) adaptedMessage else null
} else {
null
}
}.let(::listOfNotNull)
}.subscribeSafelyWithoutExceptionsAsync(
scope,
markerFactory::invoke
) { triggerMessage ->
doInSubContextWithUpdatesFilter(
updatesFilter = if (includeFilterByChatInBehaviourSubContext) {
{ it.sourceChat() ?.id ?.chatId == triggerMessage.chat.id.chatId }
} else null,
stopOnCompletion = false
) {
scenarioReceiver(triggerMessage)
}
) = on(markerFactory, initialFilter, subcontextUpdatesFilter, scenarioReceiver) {
(it.asBaseSentMessageUpdate() ?.data ?.asChatEventMessage() ?.takeIf { it.chatEvent is T } as? ChatEventMessage<T>) ?.let(::listOfNotNull)
}
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onChannelEvent(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<ChatEventMessage<ChannelEvent>>? = null,
markerFactory: MarkerFactory<in ChatEventMessage<ChannelEvent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<ChannelEvent>>
) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onChatEvent(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<ChatEventMessage<ChatEvent>>? = null,
markerFactory: MarkerFactory<in ChatEventMessage<ChatEvent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<ChatEvent>>
) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onVoiceChatEvent(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<ChatEventMessage<VoiceChatEvent>>? = null,
markerFactory: MarkerFactory<in ChatEventMessage<VoiceChatEvent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<VoiceChatEvent>>
) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onVoiceChatStartedEvent(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<ChatEventMessage<VoiceChatStarted>>? = null,
markerFactory: MarkerFactory<in ChatEventMessage<VoiceChatStarted>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<VoiceChatStarted>>
) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onVoiceChatEndedEvent(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<ChatEventMessage<VoiceChatEnded>>? = null,
markerFactory: MarkerFactory<in ChatEventMessage<VoiceChatEnded>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<VoiceChatEnded>>
) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onVoiceChatParticipantsInvitedEvent(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<ChatEventMessage<VoiceChatParticipantsInvited>>? = null,
markerFactory: MarkerFactory<in ChatEventMessage<VoiceChatParticipantsInvited>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<VoiceChatParticipantsInvited>>
) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onMessageAutoDeleteTimerChangedEvent(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<ChatEventMessage<MessageAutoDeleteTimerChanged>>? = null,
markerFactory: MarkerFactory<in ChatEventMessage<MessageAutoDeleteTimerChanged>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<MessageAutoDeleteTimerChanged>>
) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onCommonEvent(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<ChatEventMessage<CommonEvent>>? = null,
markerFactory: MarkerFactory<in ChatEventMessage<CommonEvent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<CommonEvent>>
) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onGroupEvent(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<ChatEventMessage<GroupEvent>>? = null,
markerFactory: MarkerFactory<in ChatEventMessage<GroupEvent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<GroupEvent>>
) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onSupergroupEvent(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<ChatEventMessage<SupergroupEvent>>? = null,
markerFactory: MarkerFactory<in ChatEventMessage<SupergroupEvent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<SupergroupEvent>>
) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onChannelChatCreated(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<ChatEventMessage<ChannelChatCreated>>? = null,
markerFactory: MarkerFactory<in ChatEventMessage<ChannelChatCreated>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<ChannelChatCreated>>
) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onDeleteChatPhoto(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<ChatEventMessage<DeleteChatPhoto>>? = null,
markerFactory: MarkerFactory<in ChatEventMessage<DeleteChatPhoto>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<DeleteChatPhoto>>
) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onGroupChatCreated(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<ChatEventMessage<GroupChatCreated>>? = null,
markerFactory: MarkerFactory<in ChatEventMessage<GroupChatCreated>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<GroupChatCreated>>
) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onLeftChatMember(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<ChatEventMessage<LeftChatMember>>? = null,
markerFactory: MarkerFactory<in ChatEventMessage<LeftChatMember>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<LeftChatMember>>
) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onNewChatMembers(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<ChatEventMessage<NewChatMembers>>? = null,
markerFactory: MarkerFactory<in ChatEventMessage<NewChatMembers>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<NewChatMembers>>
) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onNewChatPhoto(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<ChatEventMessage<NewChatPhoto>>? = null,
markerFactory: MarkerFactory<in ChatEventMessage<NewChatPhoto>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<NewChatPhoto>>
) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onNewChatTitle(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<ChatEventMessage<NewChatTitle>>? = null,
markerFactory: MarkerFactory<in ChatEventMessage<NewChatTitle>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<NewChatTitle>>
) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onPinnedMessage(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<ChatEventMessage<PinnedMessage>>? = null,
markerFactory: MarkerFactory<in ChatEventMessage<PinnedMessage>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<PinnedMessage>>
) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onProximityAlertTriggered(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<ChatEventMessage<ProximityAlertTriggered>>? = null,
markerFactory: MarkerFactory<in ChatEventMessage<ProximityAlertTriggered>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<ProximityAlertTriggered>>
) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onSupergroupChatCreated(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<ChatEventMessage<SupergroupChatCreated>>? = null,
markerFactory: MarkerFactory<in ChatEventMessage<SupergroupChatCreated>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<SupergroupChatCreated>>
) = onEvent(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onEvent(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onChannelEvent(
initialFilter: SimpleFilter<ChatEventMessage<ChannelEvent>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatEventMessage<ChannelEvent>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<ChannelEvent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<ChannelEvent>>
) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onChatEvent(
initialFilter: SimpleFilter<ChatEventMessage<ChatEvent>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatEventMessage<ChatEvent>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<ChatEvent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<ChatEvent>>
) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onVoiceChatEvent(
initialFilter: SimpleFilter<ChatEventMessage<VoiceChatEvent>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatEventMessage<VoiceChatEvent>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<VoiceChatEvent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<VoiceChatEvent>>
) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onVoiceChatStartedEvent(
initialFilter: SimpleFilter<ChatEventMessage<VoiceChatStarted>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatEventMessage<VoiceChatStarted>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<VoiceChatStarted>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<VoiceChatStarted>>
) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onVoiceChatEndedEvent(
initialFilter: SimpleFilter<ChatEventMessage<VoiceChatEnded>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatEventMessage<VoiceChatEnded>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<VoiceChatEnded>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<VoiceChatEnded>>
) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onVoiceChatParticipantsInvitedEvent(
initialFilter: SimpleFilter<ChatEventMessage<VoiceChatParticipantsInvited>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatEventMessage<VoiceChatParticipantsInvited>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<VoiceChatParticipantsInvited>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<VoiceChatParticipantsInvited>>
) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onMessageAutoDeleteTimerChangedEvent(
initialFilter: SimpleFilter<ChatEventMessage<MessageAutoDeleteTimerChanged>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatEventMessage<MessageAutoDeleteTimerChanged>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<MessageAutoDeleteTimerChanged>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<MessageAutoDeleteTimerChanged>>
) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onCommonEvent(
initialFilter: SimpleFilter<ChatEventMessage<CommonEvent>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatEventMessage<CommonEvent>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<CommonEvent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<CommonEvent>>
) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onGroupEvent(
initialFilter: SimpleFilter<ChatEventMessage<GroupEvent>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatEventMessage<GroupEvent>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<GroupEvent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<GroupEvent>>
) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onSupergroupEvent(
initialFilter: SimpleFilter<ChatEventMessage<SupergroupEvent>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatEventMessage<SupergroupEvent>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<SupergroupEvent>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<SupergroupEvent>>
) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onChannelChatCreated(
initialFilter: SimpleFilter<ChatEventMessage<ChannelChatCreated>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatEventMessage<ChannelChatCreated>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<ChannelChatCreated>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<ChannelChatCreated>>
) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onDeleteChatPhoto(
initialFilter: SimpleFilter<ChatEventMessage<DeleteChatPhoto>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatEventMessage<DeleteChatPhoto>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<DeleteChatPhoto>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<DeleteChatPhoto>>
) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onGroupChatCreated(
initialFilter: SimpleFilter<ChatEventMessage<GroupChatCreated>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatEventMessage<GroupChatCreated>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<GroupChatCreated>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<GroupChatCreated>>
) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onLeftChatMember(
initialFilter: SimpleFilter<ChatEventMessage<LeftChatMember>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatEventMessage<LeftChatMember>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<LeftChatMember>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<LeftChatMember>>
) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onNewChatMembers(
initialFilter: SimpleFilter<ChatEventMessage<NewChatMembers>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatEventMessage<NewChatMembers>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<NewChatMembers>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<NewChatMembers>>
) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onNewChatPhoto(
initialFilter: SimpleFilter<ChatEventMessage<NewChatPhoto>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatEventMessage<NewChatPhoto>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<NewChatPhoto>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<NewChatPhoto>>
) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onNewChatTitle(
initialFilter: SimpleFilter<ChatEventMessage<NewChatTitle>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatEventMessage<NewChatTitle>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<NewChatTitle>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<NewChatTitle>>
) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onPinnedMessage(
initialFilter: SimpleFilter<ChatEventMessage<PinnedMessage>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatEventMessage<PinnedMessage>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<PinnedMessage>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<PinnedMessage>>
) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onProximityAlertTriggered(
initialFilter: SimpleFilter<ChatEventMessage<ProximityAlertTriggered>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatEventMessage<ProximityAlertTriggered>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<ProximityAlertTriggered>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<ProximityAlertTriggered>>
) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onSupergroupChatCreated(
initialFilter: SimpleFilter<ChatEventMessage<SupergroupChatCreated>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, ChatEventMessage<SupergroupChatCreated>, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in ChatEventMessage<SupergroupChatCreated>, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, ChatEventMessage<SupergroupChatCreated>>
) = onEvent(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)

View File

@@ -1,64 +1,105 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptionsAsync
import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.expectFlow
import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.InlineQueryFilterByUser
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByUserInlineQueryMarkerFactory
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory
import dev.inmo.tgbotapi.extensions.utils.asInlineQueryUpdate
import dev.inmo.tgbotapi.extensions.utils.extensions.sourceChat
import dev.inmo.tgbotapi.types.InlineQueries.query.*
import dev.inmo.tgbotapi.types.update.abstracts.Update
internal suspend inline fun <reified T : InlineQuery> BehaviourContext.onInlineQuery(
includeFilterByChatInBehaviourSubContext: Boolean = true,
noinline additionalFilter: SimpleFilter<T>? = null,
noinline initialFilter: SimpleFilter<T>? = null,
noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, T, Update>? = InlineQueryFilterByUser,
markerFactory: MarkerFactory<in T, Any> = ByUserInlineQueryMarkerFactory,
noinline scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, T>
) = flowsUpdatesFilter.expectFlow(bot) {
it.asInlineQueryUpdate() ?.data ?.let { query ->
if (query is T) {
if (additionalFilter == null || additionalFilter(query)) query else null
} else {
null
}
}.let(::listOfNotNull)
}.subscribeSafelyWithoutExceptionsAsync(
scope,
markerFactory::invoke
) { triggerQuery ->
doInSubContextWithUpdatesFilter(
updatesFilter = if (includeFilterByChatInBehaviourSubContext) {
{ it.sourceChat() ?.id ?.chatId == triggerQuery.from.id.chatId }
} else {
null
},
stopOnCompletion = false
) {
scenarioReceiver(triggerQuery)
}
) = on(markerFactory, initialFilter, subcontextUpdatesFilter, scenarioReceiver) {
(it.asInlineQueryUpdate() ?.data as? T) ?.let(::listOfNotNull)
}
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onAnyInlineQuery(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<InlineQuery>? = null,
markerFactory: MarkerFactory<in InlineQuery, Any> = ByUserInlineQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, InlineQuery>
) = onInlineQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onInlineQuery(additionalFilter, if (includeFilterByChatInBehaviourSubContext) InlineQueryFilterByUser else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onBaseInlineQuery(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<BaseInlineQuery>? = null,
markerFactory: MarkerFactory<in BaseInlineQuery, Any> = ByUserInlineQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, BaseInlineQuery>
) = onInlineQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onInlineQuery(additionalFilter, if (includeFilterByChatInBehaviourSubContext) InlineQueryFilterByUser else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onLocationInlineQuery(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<LocationInlineQuery>? = null,
markerFactory: MarkerFactory<in LocationInlineQuery, Any> = ByUserInlineQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, LocationInlineQuery>
) = onInlineQuery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onInlineQuery(additionalFilter, if (includeFilterByChatInBehaviourSubContext) InlineQueryFilterByUser else null, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onAnyInlineQuery(
initialFilter: SimpleFilter<InlineQuery>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, InlineQuery, Update>? = InlineQueryFilterByUser,
markerFactory: MarkerFactory<in InlineQuery, Any> = ByUserInlineQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, InlineQuery>
) = onInlineQuery(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onBaseInlineQuery(
initialFilter: SimpleFilter<BaseInlineQuery>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, BaseInlineQuery, Update>? = InlineQueryFilterByUser,
markerFactory: MarkerFactory<in BaseInlineQuery, Any> = ByUserInlineQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, BaseInlineQuery>
) = onInlineQuery(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onLocationInlineQuery(
initialFilter: SimpleFilter<LocationInlineQuery>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, LocationInlineQuery, Update>? = InlineQueryFilterByUser,
markerFactory: MarkerFactory<in LocationInlineQuery, Any> = ByUserInlineQueryMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, LocationInlineQuery>
) = onInlineQuery(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)

View File

@@ -0,0 +1,33 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptionsAsync
import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.expectFlow
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory
import dev.inmo.tgbotapi.types.update.abstracts.Update
internal const val OldAPITriggersDeprecationText = "This signature of method has been deprecated. Use signature with the" +
" same name and subcontextUpdatesFilter/initialFilter instead"
internal suspend inline fun <reified T> BehaviourContext.on(
markerFactory: MarkerFactory<in T, Any>,
noinline initialFilter: SimpleFilter<T>? = null,
noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, T, Update>? = null,
noinline scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, T>,
noinline updateToData: (Update) -> List<T>?
) = flowsUpdatesFilter.expectFlow(bot) {
updateToData(it) ?.mapNotNull { data ->
if (initialFilter ?.invoke(data) != false) data else null
} ?: emptyList()
}.subscribeSafelyWithoutExceptionsAsync(
scope,
markerFactory::invoke
) { triggerData ->
doInSubContextWithUpdatesFilter(
updatesFilter = subcontextUpdatesFilter ?.toOneType(triggerData),
stopOnCompletion = false
) {
scenarioReceiver(triggerData)
}
}

View File

@@ -2,90 +2,210 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptionsAsync
import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.expectFlow
import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.MessagesFilterByChat
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByChatMediaGroupMarkerFactory
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory
import dev.inmo.tgbotapi.extensions.utils.asSentMediaGroupUpdate
import dev.inmo.tgbotapi.extensions.utils.extensions.sourceChat
import dev.inmo.tgbotapi.extensions.utils.shortcuts.chat
import dev.inmo.tgbotapi.types.message.abstracts.MediaGroupMessage
import dev.inmo.tgbotapi.types.message.content.abstracts.*
import dev.inmo.tgbotapi.types.message.content.media.PhotoContent
import dev.inmo.tgbotapi.types.message.content.media.VideoContent
import dev.inmo.tgbotapi.types.update.abstracts.Update
import dev.inmo.tgbotapi.utils.PreviewFeature
@PreviewFeature
internal suspend inline fun <reified T : MediaGroupContent> BehaviourContext.buildMediaGroupTrigger(
includeFilterByChatInBehaviourSubContext: Boolean = true,
noinline additionalFilter: SimpleFilter<List<MediaGroupMessage<T>>>? = null,
noinline initialFilter: SimpleFilter<List<MediaGroupMessage<T>>>? = null,
noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, List<MediaGroupMessage<T>>, Update>? = MessagesFilterByChat,
markerFactory: MarkerFactory<in List<MediaGroupMessage<T>>, Any> = ByChatMediaGroupMarkerFactory,
noinline scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, List<MediaGroupMessage<T>>>
) = flowsUpdatesFilter.expectFlow(bot) { update ->
update.asSentMediaGroupUpdate() ?.data ?.let { mediaGroup ->
if (mediaGroup.all { message -> message.content is T } && (additionalFilter == null || additionalFilter(mediaGroup as List<MediaGroupMessage<T>>))) {
listOf(mediaGroup as List<MediaGroupMessage<T>>)
} else {
null
}
} ?: emptyList()
}.subscribeSafelyWithoutExceptionsAsync(
scope,
markerFactory::invoke
) { mediaGroup ->
val mediaGroupChat = mediaGroup.chat!!
doInSubContextWithUpdatesFilter(
updatesFilter = if (includeFilterByChatInBehaviourSubContext) {
{ it.sourceChat() ?.id ?.chatId == mediaGroupChat.id.chatId }
} else null,
stopOnCompletion = false
) {
scenarioReceiver(mediaGroup)
}
) = on(markerFactory, initialFilter, subcontextUpdatesFilter, scenarioReceiver) {
(it.asSentMediaGroupUpdate() ?.data ?.takeIf { it.all { it is T } } as? List<MediaGroupMessage<T>>) ?.let(::listOfNotNull)
}
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onMediaGroup(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<List<MediaGroupMessage<MediaGroupContent>>>? = null,
markerFactory: MarkerFactory<in List<MediaGroupMessage<MediaGroupContent>>, Any> = ByChatMediaGroupMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, List<MediaGroupMessage<MediaGroupContent>>>
) = buildMediaGroupTrigger(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = buildMediaGroupTrigger(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessagesFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onPlaylist(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<List<MediaGroupMessage<AudioMediaGroupContent>>>? = null,
markerFactory: MarkerFactory<in List<MediaGroupMessage<AudioMediaGroupContent>>, Any> = ByChatMediaGroupMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, List<MediaGroupMessage<AudioMediaGroupContent>>>
) = buildMediaGroupTrigger(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = buildMediaGroupTrigger(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessagesFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onDocumentsGroup(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<List<MediaGroupMessage<DocumentMediaGroupContent>>>? = null,
markerFactory: MarkerFactory<in List<MediaGroupMessage<DocumentMediaGroupContent>>, Any> = ByChatMediaGroupMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, List<MediaGroupMessage<DocumentMediaGroupContent>>>
) = buildMediaGroupTrigger(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = buildMediaGroupTrigger(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessagesFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onVisualGallery(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<List<MediaGroupMessage<VisualMediaGroupContent>>>? = null,
markerFactory: MarkerFactory<in List<MediaGroupMessage<VisualMediaGroupContent>>, Any> = ByChatMediaGroupMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, List<MediaGroupMessage<VisualMediaGroupContent>>>
) = buildMediaGroupTrigger(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = buildMediaGroupTrigger(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessagesFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onVisualMediaGroup(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<List<MediaGroupMessage<VisualMediaGroupContent>>>? = null,
markerFactory: MarkerFactory<in List<MediaGroupMessage<VisualMediaGroupContent>>, Any> = ByChatMediaGroupMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, List<MediaGroupMessage<VisualMediaGroupContent>>>
) = onVisualGallery(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = onVisualGallery(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessagesFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onPhotoGallery(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<List<MediaGroupMessage<PhotoContent>>>? = null,
markerFactory: MarkerFactory<in List<MediaGroupMessage<PhotoContent>>, Any> = ByChatMediaGroupMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, List<MediaGroupMessage<PhotoContent>>>
) = buildMediaGroupTrigger(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = buildMediaGroupTrigger(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessagesFilterByChat else null, markerFactory, scenarioReceiver)
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onVideoGallery(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<List<MediaGroupMessage<VideoContent>>>? = null,
markerFactory: MarkerFactory<in List<MediaGroupMessage<VideoContent>>, Any> = ByChatMediaGroupMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, List<MediaGroupMessage<VideoContent>>>
) = buildMediaGroupTrigger(includeFilterByChatInBehaviourSubContext, additionalFilter, markerFactory, scenarioReceiver)
) = buildMediaGroupTrigger(additionalFilter, if (includeFilterByChatInBehaviourSubContext) MessagesFilterByChat else null, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onMediaGroup(
initialFilter: SimpleFilter<List<MediaGroupMessage<MediaGroupContent>>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, List<MediaGroupMessage<MediaGroupContent>>, Update>? = MessagesFilterByChat,
markerFactory: MarkerFactory<in List<MediaGroupMessage<MediaGroupContent>>, Any> = ByChatMediaGroupMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, List<MediaGroupMessage<MediaGroupContent>>>
) = buildMediaGroupTrigger(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onPlaylist(
initialFilter: SimpleFilter<List<MediaGroupMessage<AudioMediaGroupContent>>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, List<MediaGroupMessage<AudioMediaGroupContent>>, Update>? = MessagesFilterByChat,
markerFactory: MarkerFactory<in List<MediaGroupMessage<AudioMediaGroupContent>>, Any> = ByChatMediaGroupMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, List<MediaGroupMessage<AudioMediaGroupContent>>>
) = buildMediaGroupTrigger(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onDocumentsGroup(
initialFilter: SimpleFilter<List<MediaGroupMessage<DocumentMediaGroupContent>>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, List<MediaGroupMessage<DocumentMediaGroupContent>>, Update>? = MessagesFilterByChat,
markerFactory: MarkerFactory<in List<MediaGroupMessage<DocumentMediaGroupContent>>, Any> = ByChatMediaGroupMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, List<MediaGroupMessage<DocumentMediaGroupContent>>>
) = buildMediaGroupTrigger(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onVisualGallery(
initialFilter: SimpleFilter<List<MediaGroupMessage<VisualMediaGroupContent>>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, List<MediaGroupMessage<VisualMediaGroupContent>>, Update>? = MessagesFilterByChat,
markerFactory: MarkerFactory<in List<MediaGroupMessage<VisualMediaGroupContent>>, Any> = ByChatMediaGroupMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, List<MediaGroupMessage<VisualMediaGroupContent>>>
) = buildMediaGroupTrigger(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onVisualMediaGroup(
initialFilter: SimpleFilter<List<MediaGroupMessage<VisualMediaGroupContent>>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, List<MediaGroupMessage<VisualMediaGroupContent>>, Update>? = MessagesFilterByChat,
markerFactory: MarkerFactory<in List<MediaGroupMessage<VisualMediaGroupContent>>, Any> = ByChatMediaGroupMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, List<MediaGroupMessage<VisualMediaGroupContent>>>
) = onVisualGallery(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onPhotoGallery(
initialFilter: SimpleFilter<List<MediaGroupMessage<PhotoContent>>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, List<MediaGroupMessage<PhotoContent>>, Update>? = MessagesFilterByChat,
markerFactory: MarkerFactory<in List<MediaGroupMessage<PhotoContent>>, Any> = ByChatMediaGroupMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, List<MediaGroupMessage<PhotoContent>>>
) = buildMediaGroupTrigger(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onVideoGallery(
initialFilter: SimpleFilter<List<MediaGroupMessage<VideoContent>>>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, List<MediaGroupMessage<VideoContent>>, Update>? = MessagesFilterByChat,
markerFactory: MarkerFactory<in List<MediaGroupMessage<VideoContent>>, Any> = ByChatMediaGroupMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, List<MediaGroupMessage<VideoContent>>>
) = buildMediaGroupTrigger(initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)

View File

@@ -1,52 +1,59 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptionsAsync
import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.expectFlow
import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.MessageFilterByChat
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.SimpleFilter
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByChatMessageMarkerFactory
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory
import dev.inmo.tgbotapi.extensions.utils.asMessageUpdate
import dev.inmo.tgbotapi.extensions.utils.asPassportMessage
import dev.inmo.tgbotapi.extensions.utils.extensions.sourceChat
import dev.inmo.tgbotapi.types.message.PassportMessage
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.EncryptedPassportElement
import dev.inmo.tgbotapi.types.update.abstracts.Update
internal suspend inline fun <reified T : EncryptedPassportElement> BehaviourContext.onPassportMessageWith(
includeFilterByChatInBehaviourSubContext: Boolean = true,
noinline additionalFilter: SimpleFilter<PassportMessage>? = null,
noinline initialFilter: SimpleFilter<PassportMessage>? = null,
noinline subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, PassportMessage, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in PassportMessage, Any> = ByChatMessageMarkerFactory,
noinline scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, PassportMessage>
) = flowsUpdatesFilter.expectFlow(bot) {
it.asMessageUpdate() ?.data ?.asPassportMessage() ?.let { message ->
if (message.passportData.data.any { it is T }) {
if (additionalFilter == null || additionalFilter(message)) message else null
} else {
null
}
}.let(::listOfNotNull)
}.subscribeSafelyWithoutExceptionsAsync(
scope,
markerFactory::invoke
) { triggerMessage ->
doInSubContextWithUpdatesFilter(
updatesFilter = if (includeFilterByChatInBehaviourSubContext) {
{ it.sourceChat() ?.id ?.chatId == triggerMessage.chat.id.chatId }
} else null,
stopOnCompletion = false
) {
scenarioReceiver(triggerMessage)
}
) = on(markerFactory, initialFilter, subcontextUpdatesFilter, scenarioReceiver) {
(it.asMessageUpdate() ?.data ?.asPassportMessage() ?.takeIf { it.passportData.data.any { it is T } }) ?.let(::listOfNotNull)
}
@Deprecated(OldAPITriggersDeprecationText)
suspend fun BehaviourContext.onPassportMessage(
includeFilterByChatInBehaviourSubContext: Boolean = true,
includeFilterByChatInBehaviourSubContext: Boolean,
additionalFilter: SimpleFilter<PassportMessage>? = null,
markerFactory: MarkerFactory<in PassportMessage, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, PassportMessage>
) = onPassportMessageWith<EncryptedPassportElement>(
includeFilterByChatInBehaviourSubContext,
additionalFilter,
if (includeFilterByChatInBehaviourSubContext) MessageFilterByChat else null,
markerFactory,
scenarioReceiver
)
/**
* @param initialFilter This filter will be called to remove unnecessary data BEFORE [scenarioReceiver] call
* @param subcontextUpdatesFilter This filter will be applied to each update inside of [scenarioReceiver]. For example,
* this filter will be used if you will call [dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitContentMessage].
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver] function to create your own.
* Use [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.plus] or [dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times]
* to combinate several filters
* @param [markerFactory] Will be used to identify different "stream". [scenarioReceiver] will be called synchronously
* in one "stream". Output of [markerFactory] will be used as a key for "stream"
* @param scenarioReceiver Main callback which will be used to handle incoming data if [initialFilter] will pass that
* data
*/
suspend fun BehaviourContext.onPassportMessage(
initialFilter: SimpleFilter<PassportMessage>? = null,
subcontextUpdatesFilter: BehaviourContextAndTwoTypesReceiver<Boolean, PassportMessage, Update>? = MessageFilterByChat,
markerFactory: MarkerFactory<in PassportMessage, Any> = ByChatMessageMarkerFactory,
scenarioReceiver: BehaviourContextAndTypeReceiver<Unit, PassportMessage>
) = onPassportMessageWith<EncryptedPassportElement>(
initialFilter,
subcontextUpdatesFilter,
markerFactory,
scenarioReceiver
)

View File

@@ -0,0 +1,30 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder.utils
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTypeReceiver
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitEditedLocation
import dev.inmo.tgbotapi.types.location.*
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.content.LiveLocationContent
/**
* Use this extension when you want to follow [LiveLocation] until it will became [StaticLocation]. This method
* is synchronous. You may use something like [kotlinx.coroutines.launch] or [kotlinx.coroutines.async] to run it
* asynchronously
*/
suspend fun BehaviourContext.followLocation(
message: ContentMessage<LiveLocationContent>,
onLocation: BehaviourContextAndTypeReceiver<Unit, Location>
) {
var currentLocation: Location = message.content.location
onLocation(message.content.location)
while (currentLocation !is StaticLocation) {
currentLocation = waitEditedLocation(
filter = {
it.messageId == message.messageId && it.chat.id == message.chat.id
}
).first().location
onLocation(currentLocation)
}
}

View File

@@ -1,3 +1,26 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder.utils
typealias SimpleFilter<T> = suspend (T) -> Boolean
inline fun <T> SimpleFilter(noinline block: SimpleFilter<T>) = block
/**
* Makes an AND (&&) operation between [this] and [other]
*/
operator fun <T> SimpleFilter<T>.times(other: SimpleFilter<T>): SimpleFilter<T> = {
this(it) && other(it)
}
/**
* Makes an OR (||) operation between [this] and [other]
*/
operator fun <T> SimpleFilter<T>.plus(other: SimpleFilter<T>): SimpleFilter<T> = {
this(it) || other(it)
}
/**
* Reverse results of [this]
*/
operator fun <T> SimpleFilter<T>.not(): SimpleFilter<T> = {
!this(it)
}

View File

@@ -0,0 +1,29 @@
package dev.inmo.tgbotapi.extensions.behaviour_builder.utils
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextAndTwoTypesReceiver
import dev.inmo.tgbotapi.types.update.abstracts.Update
/**
* Makes an OR (||) operation between [this] and [other]
*/
operator fun <T> (BehaviourContextAndTwoTypesReceiver<Boolean, T, Update>).plus(
other: BehaviourContextAndTwoTypesReceiver<Boolean, T, Update>
) = BehaviourContextAndTwoTypesReceiver<Boolean, T, Update> { t, update ->
this@plus(t, update) || other(t, update)
}
/**
* Makes an AND (&&) operation between [this] and [other]
*/
operator fun <T> (BehaviourContextAndTwoTypesReceiver<Boolean, T, Update>).times(
other: BehaviourContextAndTwoTypesReceiver<Boolean, T, Update>
) = BehaviourContextAndTwoTypesReceiver<Boolean, T, Update> { t, update ->
this@times(t, update) && other(t, update)
}
/**
* Reverse results of [this]
*/
operator fun <T> (BehaviourContextAndTwoTypesReceiver<Boolean, T, Update>).not() = BehaviourContextAndTwoTypesReceiver<Boolean, T, Update> { t, update ->
!this@not(t, update)
}

View File

@@ -1,5 +1,6 @@
# TelegramBotAPI Util Extensions
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.utils/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.utils)
- [TelegramBotAPI Util Extensions](#telegrambotapi-util-extensions)
* [What is it?](#what-is-it)
@@ -9,7 +10,7 @@
* [How to use?](#how-to-use)
+ [Updates](#updates)
- [Long polling](#long-polling)
- [WebHooks (currently JVM-only)](#webhooks--currently-jvm-only)
- [WebHooks (currently JVM-only)](#webhooks-currently-jvm-only)
+ [Filters](#filters)
- [Sent messages](#sent-messages)
* [Common messages](#common-messages)
@@ -19,9 +20,6 @@
<small><i><a href='http://ecotrust-canada.github.io/markdown-toc/'>Table of contents generated with markdown-toc</a></i></small>
[![Download](https://api.bintray.com/packages/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.utils/images/download.svg) ](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.utils/_latestVersion)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.utils/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.utils)
## What is it?
It is wrapper library for [TelegramBotAPI Core](../tgbotapi.core/README.md). Currently, this library contains some usefull filters for commands, updates types and different others.

View File

@@ -32,6 +32,7 @@ import dev.inmo.tgbotapi.types.chat.abstracts.extended.*
import dev.inmo.tgbotapi.types.dice.*
import dev.inmo.tgbotapi.types.files.*
import dev.inmo.tgbotapi.types.files.abstracts.*
import dev.inmo.tgbotapi.types.location.*
import dev.inmo.tgbotapi.types.message.*
import dev.inmo.tgbotapi.types.message.ChatEvents.*
import dev.inmo.tgbotapi.types.message.ChatEvents.LeftChatMember
@@ -2506,6 +2507,24 @@ inline fun ResendableContent.asLocationContent(): LocationContent? = this as? Lo
@PreviewFeature
inline fun ResendableContent.requireLocationContent(): LocationContent = this as LocationContent
@PreviewFeature
inline fun <T> ResendableContent.whenLiveLocationContent(block: (LiveLocationContent) -> T) = asLiveLocationContent() ?.let(block)
@PreviewFeature
inline fun ResendableContent.asLiveLocationContent(): LiveLocationContent? = this as? LiveLocationContent
@PreviewFeature
inline fun ResendableContent.requireLiveLocationContent(): LiveLocationContent = this as LiveLocationContent
@PreviewFeature
inline fun <T> ResendableContent.whenStaticLocationContent(block: (StaticLocationContent) -> T) = asStaticLocationContent() ?.let(block)
@PreviewFeature
inline fun ResendableContent.asStaticLocationContent(): StaticLocationContent? = this as? StaticLocationContent
@PreviewFeature
inline fun ResendableContent.requireStaticLocationContent(): StaticLocationContent = this as StaticLocationContent
@PreviewFeature
inline fun <T> ResendableContent.whenPollContent(block: (PollContent) -> T) = asPollContent() ?.let(block)
@@ -3116,3 +3135,21 @@ inline fun Any.asWithOptionalLanguageCode(): WithOptionalLanguageCode? = this as
@PreviewFeature
inline fun Any.requireWithOptionalLanguageCode(): WithOptionalLanguageCode = this as WithOptionalLanguageCode
@PreviewFeature
inline fun <T> Location.whenStaticLocation(block: (StaticLocation) -> T) = asStaticLocation() ?.let(block)
@PreviewFeature
inline fun Location.asStaticLocation(): StaticLocation? = this as? StaticLocation
@PreviewFeature
inline fun Location.requireStaticLocation(): StaticLocation = this as StaticLocation
@PreviewFeature
inline fun <T> Location.whenLiveLocation(block: (LiveLocation) -> T) = asLiveLocation() ?.let(block)
@PreviewFeature
inline fun Location.asLiveLocation(): LiveLocation? = this as? LiveLocation
@PreviewFeature
inline fun Location.requireLiveLocation(): LiveLocation = this as LiveLocation

View File

@@ -6,14 +6,16 @@ import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.merge
@Deprecated("Will be removed soon", ReplaceWith("messagesFlow + channelPostsFlow"))
val FlowsUpdatesFilter.allSentMessagesFlow: Flow<BaseSentMessageUpdate>
get() = merge(
messageFlow,
channelPostFlow
messagesFlow,
channelPostsFlow
)
@Deprecated("Will be removed soon", ReplaceWith("messageMediaGroupsFlow + channelPostMediaGroupsFlow"))
val FlowsUpdatesFilter.allSentMediaGroupsFlow: Flow<SentMediaGroupUpdate>
get() = merge(
messageMediaGroupFlow,
channelPostMediaGroupFlow
messageMediaGroupsFlow,
channelPostMediaGroupsFlow
)

View File

@@ -6,6 +6,7 @@ import dev.inmo.tgbotapi.types.MessageEntity.textsources.*
import dev.inmo.tgbotapi.types.User
typealias EntitiesBuilderBody = EntitiesBuilder.() -> Unit
val newLine = regular("\n")
fun buildEntities(init: EntitiesBuilderBody): TextSourcesList = EntitiesBuilder().apply(init).build()
@@ -59,116 +60,395 @@ class EntitiesBuilder internal constructor(
}
}
/**
* Add bold using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.bold]
*/
inline fun EntitiesBuilder.bold(parts: TextSourcesList) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.bold(parts))
/**
* Version of [EntitiesBuilder.bold] with new line at the end
*/
inline fun EntitiesBuilder.boldln(parts: TextSourcesList) = bold(parts) + newLine
/**
* Add bold using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.bold]
*/
inline fun EntitiesBuilder.bold(noinline init: EntitiesBuilderBody) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.bold(buildEntities(init)))
inline fun EntitiesBuilder.bold(vararg parts: TextSource) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.bold(*parts))
/**
* Version of [EntitiesBuilder.bold] with new line at the end
*/
inline fun EntitiesBuilder.boldln(noinline init: EntitiesBuilderBody) = bold(init) + newLine
/**
* Add bold using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.bold]
*/
inline fun EntitiesBuilder.bold(vararg parts: TextSource) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.bold(*parts))
/**
* Version of [EntitiesBuilder.bold] with new line at the end
*/
inline fun EntitiesBuilder.boldln(vararg parts: TextSource) = bold(*parts) + newLine
/**
* Add bold using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.bold]
*/
inline fun EntitiesBuilder.bold(text: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.bold(text))
/**
* Version of [EntitiesBuilder.bold] with new line at the end
*/
inline fun EntitiesBuilder.boldln(text: String) = bold(text) + newLine
inline fun EntitiesBuilder.botCommand(command: String) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.botCommand(command))
inline fun EntitiesBuilder.cashTag(parts: TextSourcesList) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.cashTag(parts))
/**
* Add botCommand using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.botCommand]
*/
inline fun EntitiesBuilder.botCommand(command: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.botCommand(command))
/**
* Version of [EntitiesBuilder.botCommand] with new line at the end
*/
inline fun EntitiesBuilder.botCommandln(command: String) = botCommand(command) + newLine
/**
* Add cashTag using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.cashTag]
*/
inline fun EntitiesBuilder.cashTag(parts: TextSourcesList) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.cashTag(parts))
/**
* Version of [EntitiesBuilder.cashTag] with new line at the end
*/
inline fun EntitiesBuilder.cashTagln(parts: TextSourcesList) = cashTag(parts) + newLine
/**
* Add cashTag using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.cashTag]
*/
inline fun EntitiesBuilder.cashTag(noinline init: EntitiesBuilderBody) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.cashTag(buildEntities(init)))
inline fun EntitiesBuilder.cashTag(vararg parts: TextSource) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.cashTag(*parts))
/**
* Version of [EntitiesBuilder.cashTag] with new line at the end
*/
inline fun EntitiesBuilder.cashTagln(noinline init: EntitiesBuilderBody) = cashTag(init) + newLine
/**
* Add cashTag using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.cashTag]
*/
inline fun EntitiesBuilder.cashTag(vararg parts: TextSource) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.cashTag(*parts))
/**
* Version of [EntitiesBuilder.cashTag] with new line at the end
*/
inline fun EntitiesBuilder.cashTagln(vararg parts: TextSource) = cashTag(*parts) + newLine
/**
* Add cashTag using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.cashTag]
*/
inline fun EntitiesBuilder.cashTag(text: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.cashTag(text))
/**
* Version of [EntitiesBuilder.cashTag] with new line at the end
*/
inline fun EntitiesBuilder.cashTagln(text: String) = cashTag(text) + newLine
/**
* Add code using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.code]
*/
inline fun EntitiesBuilder.code(code: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.code(code))
/**
* Version of [EntitiesBuilder.code] with new line at the end
*/
inline fun EntitiesBuilder.codeln(code: String) = code(code) + newLine
inline fun EntitiesBuilder.email(parts: TextSourcesList) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.email(parts))
/**
* Add email using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.email]
*/
inline fun EntitiesBuilder.email(parts: TextSourcesList) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.email(parts))
/**
* Version of [EntitiesBuilder.email] with new line at the end
*/
inline fun EntitiesBuilder.emailln(parts: TextSourcesList) = email(parts) + newLine
/**
* Add email using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.email]
*/
inline fun EntitiesBuilder.email(noinline init: EntitiesBuilderBody) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.email(buildEntities(init)))
/**
* Version of [EntitiesBuilder.email] with new line at the end
*/
inline fun EntitiesBuilder.emailln(noinline init: EntitiesBuilderBody) = email(init) + newLine
/**
* Add email using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.email]
*/
inline fun EntitiesBuilder.email(vararg parts: TextSource) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.email(*parts))
/**
* Version of [EntitiesBuilder.email] with new line at the end
*/
inline fun EntitiesBuilder.emailln(vararg parts: TextSource) = email(*parts) + newLine
/**
* Add email using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.email]
*/
inline fun EntitiesBuilder.email(emailAddress: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.email(emailAddress))
/**
* Version of [EntitiesBuilder.email] with new line at the end
*/
inline fun EntitiesBuilder.emailln(emailAddress: String) = email(emailAddress) + newLine
inline fun EntitiesBuilder.email(vararg parts: TextSource) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.email(*parts))
inline fun EntitiesBuilder.email(emailAddress: String) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.email(emailAddress))
inline fun EntitiesBuilder.hashtag(parts: TextSourcesList) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.hashtag(parts))
/**
* Add hashtag using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.hashtag]
*/
inline fun EntitiesBuilder.hashtag(parts: TextSourcesList) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.hashtag(parts))
/**
* Version of [EntitiesBuilder.hashtag] with new line at the end
*/
inline fun EntitiesBuilder.hashtagln(parts: TextSourcesList) = hashtag(parts) + newLine
/**
* Add hashtag using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.hashtag]
*/
inline fun EntitiesBuilder.hashtag(noinline init: EntitiesBuilderBody) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.hashtag(buildEntities(init)))
inline fun EntitiesBuilder.hashtag(vararg parts: TextSource) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.hashtag(*parts))
/**
* Version of [EntitiesBuilder.hashtag] with new line at the end
*/
inline fun EntitiesBuilder.hashtagln(noinline init: EntitiesBuilderBody) = hashtag(init) + newLine
/**
* Add hashtag using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.hashtag]
*/
inline fun EntitiesBuilder.hashtag(vararg parts: TextSource) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.hashtag(*parts))
/**
* Version of [EntitiesBuilder.hashtag] with new line at the end
*/
inline fun EntitiesBuilder.hashtagln(vararg parts: TextSource) = hashtag(*parts) + newLine
/**
* Add hashtag using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.hashtag]
*/
inline fun EntitiesBuilder.hashtag(hashtag: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.hashtag(hashtag))
/**
* Version of [EntitiesBuilder.hashtag] with new line at the end
*/
inline fun EntitiesBuilder.hashtagln(hashtag: String) = hashtag(hashtag) + newLine
inline fun EntitiesBuilder.italic(parts: TextSourcesList) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.italic(parts))
/**
* Add italic using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.italic]
*/
inline fun EntitiesBuilder.italic(parts: TextSourcesList) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.italic(parts))
/**
* Version of [EntitiesBuilder.italic] with new line at the end
*/
inline fun EntitiesBuilder.italicln(parts: TextSourcesList) = italic(parts) + newLine
/**
* Add italic using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.italic]
*/
inline fun EntitiesBuilder.italic(noinline init: EntitiesBuilderBody) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.italic(buildEntities(init)))
inline fun EntitiesBuilder.italic(vararg parts: TextSource) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.italic(*parts))
/**
* Version of [EntitiesBuilder.italic] with new line at the end
*/
inline fun EntitiesBuilder.italicln(noinline init: EntitiesBuilderBody) = italic(init) + newLine
/**
* Add italic using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.italic]
*/
inline fun EntitiesBuilder.italic(vararg parts: TextSource) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.italic(*parts))
/**
* Version of [EntitiesBuilder.italic] with new line at the end
*/
inline fun EntitiesBuilder.italicln(vararg parts: TextSource) = italic(*parts) + newLine
/**
* Add italic using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.italic]
*/
inline fun EntitiesBuilder.italic(text: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.italic(text))
/**
* Version of [EntitiesBuilder.italic] with new line at the end
*/
inline fun EntitiesBuilder.italicln(text: String) = italic(text) + newLine
inline fun EntitiesBuilder.mention(parts: TextSourcesList) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(parts))
/**
* Add mention using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.mention]
*/
inline fun EntitiesBuilder.mention(parts: TextSourcesList) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(parts))
/**
* Version of [EntitiesBuilder.mention] with new line at the end
*/
inline fun EntitiesBuilder.mentionln(parts: TextSourcesList) = mention(parts) + newLine
/**
* Add mention using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.mention]
*/
inline fun EntitiesBuilder.mention(noinline init: EntitiesBuilderBody) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(buildEntities(init)))
inline fun EntitiesBuilder.mention(vararg parts: TextSource) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(*parts))
inline fun EntitiesBuilder.mention(whoToMention: String) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(whoToMention))
inline fun EntitiesBuilder.mention(parts: TextSourcesList, user: User) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(parts, user))
/**
* Version of [EntitiesBuilder.mention] with new line at the end
*/
inline fun EntitiesBuilder.mentionln(noinline init: EntitiesBuilderBody) = mention(init) + newLine
/**
* Add mention using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.mention]
*/
inline fun EntitiesBuilder.mention(vararg parts: TextSource) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(*parts))
/**
* Version of [EntitiesBuilder.mention] with new line at the end
*/
inline fun EntitiesBuilder.mentionln(vararg parts: TextSource) = mention(*parts) + newLine
/**
* Add mention using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.mention]
*/
inline fun EntitiesBuilder.mention(whoToMention: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(whoToMention))
/**
* Version of [EntitiesBuilder.mention] with new line at the end
*/
inline fun EntitiesBuilder.mentionln(whoToMention: String) = mention(whoToMention) + newLine
/**
* Add mention using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.mention]
*/
inline fun EntitiesBuilder.mention(parts: TextSourcesList, user: User) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(parts, user))
/**
* Version of [EntitiesBuilder.mention] with new line at the end
*/
inline fun EntitiesBuilder.mentionln(parts: TextSourcesList, user: User) = mention(parts) + newLine
inline fun EntitiesBuilder.mention(
user: User,
vararg parts: TextSource
) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(user, *parts))
) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(user, *parts))
/**
* Version of [EntitiesBuilder.mention] with new line at the end
*/
inline fun EntitiesBuilder.mentionln(user: User, vararg parts: TextSource) = mention(user, *parts) + newLine
/**
* Add mention using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.mention]
*/
inline fun EntitiesBuilder.mention(text: String, user: User) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(text, user))
/**
* Version of [EntitiesBuilder.mention] with new line at the end
*/
inline fun EntitiesBuilder.mentionln(text: String, user: User) = mention(text) + newLine
inline fun EntitiesBuilder.mention(text: String, user: User) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.mention(text, user))
inline fun EntitiesBuilder.phone(parts: TextSourcesList) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.phone(parts))
/**
* Add phone using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.phone]
*/
inline fun EntitiesBuilder.phone(parts: TextSourcesList) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.phone(parts))
/**
* Version of [EntitiesBuilder.phone] with new line at the end
*/
inline fun EntitiesBuilder.phoneln(parts: TextSourcesList) = phone(parts) + newLine
/**
* Add phone using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.phone]
*/
inline fun EntitiesBuilder.phone(noinline init: EntitiesBuilderBody) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.phone(buildEntities(init)))
/**
* Version of [EntitiesBuilder.phone] with new line at the end
*/
inline fun EntitiesBuilder.phoneln(noinline init: EntitiesBuilderBody) = phone(init) + newLine
/**
* Add phone using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.phone]
*/
inline fun EntitiesBuilder.phone(vararg parts: TextSource) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.phone(*parts))
/**
* Version of [EntitiesBuilder.phone] with new line at the end
*/
inline fun EntitiesBuilder.phoneln(vararg parts: TextSource) = phone(*parts) + newLine
/**
* Add phone using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.phone]
*/
inline fun EntitiesBuilder.phone(number: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.phone(number))
/**
* Version of [EntitiesBuilder.phone] with new line at the end
*/
inline fun EntitiesBuilder.phoneln(number: String) = phone(number) + newLine
inline fun EntitiesBuilder.phone(vararg parts: TextSource) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.phone(*parts))
inline fun EntitiesBuilder.phone(number: String) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.phone(number))
inline fun EntitiesBuilder.pre(code: String, language: String?) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.pre(code, language))
/**
* Add pre using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.pre]
*/
inline fun EntitiesBuilder.pre(code: String, language: String?) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.pre(code, language))
/**
* Version of [EntitiesBuilder.pre] with new line at the end
*/
inline fun EntitiesBuilder.preln(code: String, language: String?) = pre(code) + newLine
/**
* Will add simple [dev.inmo.tgbotapi.types.MessageEntity.textsources.regular] [TextSource]
*
* @see RegularTextSource
* @see dev.inmo.tgbotapi.extensions.utils.formatting.regularln
*/
inline fun EntitiesBuilder.regular(text: String) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.regular(text))
/**
* Will add simple [dev.inmo.tgbotapi.types.MessageEntity.textsources.regular] [TextSource] and "\n" at the end
*
* @see RegularTextSource
* @see dev.inmo.tgbotapi.extensions.utils.formatting.regular
*/
inline fun EntitiesBuilder.regularln(text: String) = regular(text) + newLine
inline fun EntitiesBuilder.strikethrough(parts: TextSourcesList) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.strikethrough(parts))
/**
* Add strikethrough using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.strikethrough]
*/
inline fun EntitiesBuilder.strikethrough(parts: TextSourcesList) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.strikethrough(parts))
/**
* Version of [EntitiesBuilder.strikethrough] with new line at the end
*/
inline fun EntitiesBuilder.strikethroughln(parts: TextSourcesList) = strikethrough(parts) + newLine
/**
* Add strikethrough using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.strikethrough]
*/
inline fun EntitiesBuilder.strikethrough(noinline init: EntitiesBuilderBody) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.strikethrough(buildEntities(init)))
/**
* Version of [EntitiesBuilder.strikethrough] with new line at the end
*/
inline fun EntitiesBuilder.strikethroughln(noinline init: EntitiesBuilderBody) = strikethrough(init) + newLine
/**
* Add strikethrough using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.strikethrough]
*/
inline fun EntitiesBuilder.strikethrough(vararg parts: TextSource) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.strikethrough(*parts))
/**
* Version of [EntitiesBuilder.strikethrough] with new line at the end
*/
inline fun EntitiesBuilder.strikethroughln(vararg parts: TextSource) = strikethrough(*parts) + newLine
/**
* Add strikethrough using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.strikethrough]
*/
inline fun EntitiesBuilder.strikethrough(text: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.strikethrough(text))
/**
* Version of [EntitiesBuilder.strikethrough] with new line at the end
*/
inline fun EntitiesBuilder.strikethroughln(text: String) = strikethrough(text) + newLine
inline fun EntitiesBuilder.strikethrough(vararg parts: TextSource) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.strikethrough(*parts))
inline fun EntitiesBuilder.strikethrough(text: String) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.strikethrough(text))
/**
* Add link using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.link]
*/
inline fun EntitiesBuilder.link(text: String, url: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.link(text, url))
/**
* Version of [EntitiesBuilder.link] with new line at the end
*/
inline fun EntitiesBuilder.linkln(text: String, url: String) = link(text) + newLine
/**
* Add link using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.link]
*/
inline fun EntitiesBuilder.link(url: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.link(url))
/**
* Version of [EntitiesBuilder.link] with new line at the end
*/
inline fun EntitiesBuilder.linkln(url: String) = link(url) + newLine
inline fun EntitiesBuilder.link(text: String, url: String) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.link(text, url))
inline fun EntitiesBuilder.link(url: String) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.link(url))
inline fun EntitiesBuilder.underline(parts: TextSourcesList) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.underline(parts))
/**
* Add underline using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.underline]
*/
inline fun EntitiesBuilder.underline(parts: TextSourcesList) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.underline(parts))
/**
* Version of [EntitiesBuilder.underline] with new line at the end
*/
inline fun EntitiesBuilder.underlineln(parts: TextSourcesList) = underline(parts) + newLine
/**
* Add underline using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.underline]
*/
inline fun EntitiesBuilder.underline(noinline init: EntitiesBuilderBody) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.underline(buildEntities(init)))
inline fun EntitiesBuilder.underline(vararg parts: TextSource) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.underline(*parts))
inline fun EntitiesBuilder.underline(text: String) =
add(dev.inmo.tgbotapi.types.MessageEntity.textsources.underline(text))
/**
* Version of [EntitiesBuilder.underline] with new line at the end
*/
inline fun EntitiesBuilder.underlineln(noinline init: EntitiesBuilderBody) = underline(init) + newLine
/**
* Add underline using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.underline]
*/
inline fun EntitiesBuilder.underline(vararg parts: TextSource) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.underline(*parts))
/**
* Version of [EntitiesBuilder.underline] with new line at the end
*/
inline fun EntitiesBuilder.underlineln(vararg parts: TextSource) = underline(*parts) + newLine
/**
* Add underline using [EntitiesBuilder.add] with [dev.inmo.tgbotapi.types.MessageEntity.textsources.underline]
*/
inline fun EntitiesBuilder.underline(text: String) = add(dev.inmo.tgbotapi.types.MessageEntity.textsources.underline(text))
/**
* Version of [EntitiesBuilder.underline] with new line at the end
*/
inline fun EntitiesBuilder.underlineln(text: String) = underline(text) + newLine

View File

@@ -14,21 +14,21 @@ import kotlinx.coroutines.flow.mapNotNull
@RiskFeature("Use with caution")
inline fun FlowsUpdatesFilter.events(): Flow<ChatEventMessage<*>> {
return channelPostFlow.mapNotNull { it.data as? ChatEventMessage<*> } + messageFlow.mapNotNull { it.data as? ChatEventMessage<*> }
return channelPostsFlow.mapNotNull { it.data as? ChatEventMessage<*> } + messagesFlow.mapNotNull { it.data as? ChatEventMessage<*> }
}
@RiskFeature("Use with caution")
inline fun FlowsUpdatesFilter.channelEvents(): Flow<ChannelEventMessage<*>> = channelPostFlow.mapNotNull {
inline fun FlowsUpdatesFilter.channelEvents(): Flow<ChannelEventMessage<*>> = channelPostsFlow.mapNotNull {
it.data as? ChannelEventMessage<*>
}
@RiskFeature("Use with caution")
inline fun FlowsUpdatesFilter.groupEvents(): Flow<GroupEventMessage<*>> = messageFlow.mapNotNull {
inline fun FlowsUpdatesFilter.groupEvents(): Flow<GroupEventMessage<*>> = messagesFlow.mapNotNull {
it.data as? GroupEventMessage<*>
}
@RiskFeature("Use with caution")
inline fun FlowsUpdatesFilter.supergroupEvents(): Flow<SupergroupEventMessage<*>> = messageFlow.mapNotNull {
inline fun FlowsUpdatesFilter.supergroupEvents(): Flow<SupergroupEventMessage<*>> = messagesFlow.mapNotNull {
it.data as? SupergroupEventMessage<*>
}

View File

@@ -47,8 +47,8 @@ inline fun <reified T : MediaGroupContent> Flow<SentMediaGroupUpdate>.filterMedi
/**
* @param scopeToIncludeChannels This parameter is required when you want to include [textMessages] for channels too.
* In this case will be created new channel which will aggregate messages from [FlowsUpdatesFilter.messageFlow] and
* [FlowsUpdatesFilter.channelPostFlow]. In case it is null will be used [Flow]s mapping
* In this case will be created new channel which will aggregate messages from [FlowsUpdatesFilter.messagesFlow] and
* [FlowsUpdatesFilter.channelPostsFlow]. In case it is null will be used [Flow]s mapping
*/
@Suppress("UNCHECKED_CAST")
@RiskFeature(lowLevelRiskFeatureMessage)
@@ -58,16 +58,16 @@ inline fun <reified T: MessageContent> FlowsUpdatesFilter.filterContentMessages(
return (scopeToIncludeChannels ?.let { scope ->
aggregateFlows(
scope,
messageFlow,
channelPostFlow
messagesFlow,
channelPostsFlow
)
} ?: messageFlow).filterContentMessages()
} ?: messagesFlow).filterContentMessages()
}
/**
* @param scopeToIncludeChannels This parameter is required when you want to include [SentMediaGroupUpdate] for channels
* too. In this case will be created new channel which will aggregate messages from [FlowsUpdatesFilter.messageFlow] and
* [FlowsUpdatesFilter.channelPostFlow]. In case it is null will be used [Flow]s mapping
* too. In this case will be created new channel which will aggregate messages from [FlowsUpdatesFilter.messagesFlow] and
* [FlowsUpdatesFilter.channelPostsFlow]. In case it is null will be used [Flow]s mapping
*/
@Suppress("UNCHECKED_CAST")
@RiskFeature(lowLevelRiskFeatureMessage)
@@ -77,10 +77,10 @@ inline fun <reified T: MediaGroupContent> FlowsUpdatesFilter.filterMediaGroupMes
return (scopeToIncludeChannels ?.let { scope ->
aggregateFlows(
scope,
messageMediaGroupFlow,
channelPostMediaGroupFlow
messageMediaGroupsFlow,
channelPostMediaGroupsFlow
)
} ?: messageMediaGroupFlow).filterMediaGroupMessages()
} ?: messageMediaGroupsFlow).filterMediaGroupMessages()
}
fun FlowsUpdatesFilter.sentMessages(

View File

@@ -4,6 +4,7 @@ import dev.inmo.micro_utils.coroutines.safely
import dev.inmo.tgbotapi.bot.RequestsExecutor
import dev.inmo.tgbotapi.requests.abstracts.Request
import kotlinx.coroutines.*
import kotlin.coroutines.coroutineContext
fun <T: Any> RequestsExecutor.executeAsync(
request: Request<T>,
@@ -16,9 +17,7 @@ fun <T: Any> RequestsExecutor.executeAsync(
suspend fun <T: Any> RequestsExecutor.executeAsync(
request: Request<T>
): Deferred<T> = coroutineScope {
executeAsync(request, this)
}
): Deferred<T> = executeAsync(request, CoroutineScope(coroutineContext))
suspend fun <T: Any> RequestsExecutor.executeUnsafe(
request: Request<T>,

View File

@@ -0,0 +1,38 @@
package dev.inmo.tgbotapi.extensions.utils.types.files
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.DownloadFileStream
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.requests.get.GetFile
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 dev.inmo.tgbotapi.utils.*
suspend fun convertToStorageFile(
downloadStreamAllocator: ByteReadChannelAllocator,
pathedFile: PathedFile
): StorageFile {
return downloadStreamAllocator.asStorageFile(
pathedFile.fileName
)
}
suspend fun TelegramBot.convertToStorageFile(
pathedFile: PathedFile
): StorageFile = convertToStorageFile(
execute(DownloadFileStream(pathedFile.filePath)),
pathedFile
)
suspend fun TelegramBot.convertToStorageFile(
fileId: FileId
): StorageFile = convertToStorageFile(execute(GetFile(fileId)))
suspend fun TelegramBot.convertToStorageFile(
file: TelegramMediaFile
): StorageFile = convertToStorageFile(file.fileId)
suspend fun TelegramBot.convertToStorageFile(
content: MediaContent
): StorageFile = convertToStorageFile(content.media)

View File

@@ -9,6 +9,7 @@ fun PathedFile.asStream(
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper
): InputStream = URL(this.fullUrl(telegramAPIUrlsKeeper)).openStream()
@Deprecated("This api will be removed soon. Use `downloadFile` instead")
fun PathedFile.asFile(
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper,
dest: File = File.createTempFile(this.fileUniqueId, this.filename),
@@ -22,6 +23,7 @@ fun PathedFile.asFile(
return dest
}
@Deprecated("This api will be removed soon. Use `downloadFile` instead")
fun PathedFile.asBytes(
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper
): ByteArray = this.asStream(telegramAPIUrlsKeeper)