mirror of
https://github.com/InsanusMokrassar/docs.git
synced 2026-04-06 02:02:28 +00:00
mkdocs inited
This commit is contained in:
37
docs/tgbotapi/logic/api-extensions.md
Normal file
37
docs/tgbotapi/logic/api-extensions.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# API Extensions
|
||||
|
||||
[API extensions](https://github.com/InsanusMokrassar/TelegramBotAPI/tree/master/tgbotapi.api) is a module which you may include in your project in addition to [core part](https://github.com/InsanusMokrassar/TelegramBotAPI/tree/master/tgbotapi.core). In most cases this module will allow just use syntax like `bot.getUpdates()` instead of `bot.execute(GetUpdates())`, but there are several other things you will achieve with that syntax.
|
||||
|
||||
## Bot builder
|
||||
|
||||
This functionality allow you to build bot in more unified and comfortable way than standard creating with `telegramBot` function
|
||||
|
||||
```kotlin
|
||||
buildBot(
|
||||
"TOKEN"
|
||||
) {
|
||||
proxy = ProxyBuilder.socks(host = "127.0.0.1", port = 4001) // just an example, more info on https://ktor.io/docs/proxy.html
|
||||
ktorClientConfig = {
|
||||
// configuring of ktor client
|
||||
}
|
||||
ktorClientEngineFactory = {
|
||||
// configuring of ktor client engine
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Downloading of files
|
||||
|
||||
In standard library requests there are no way to download some file retrieved in updates or after requests. You may use syntax like `bot.downloadFile(file)` where `file` is `TelegramMediaFile` from telegram, `FileId` or even `PathedFile` from [GetFile](https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/get/GetFile.kt) request ([sources](https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/files/DownloadFile.kt)).
|
||||
|
||||
## Live location
|
||||
|
||||
By default, you should handle updates of Live location by your code. But with extension [bot#startLiveLocation](https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/tgbotapi.api/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/api/LiveLocationProvider.kt#L84) you may provide all necessary startup parameters and handle updates with just calling `updateLocation` for retrieved [LiveLocationProvider](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.api/-live-location-provider/index.html).
|
||||
|
||||
## What is next?
|
||||
|
||||
There are several things you may read next:
|
||||
|
||||
* [Updates retrieving](https://bookstack.inmo.dev/books/telegrambotapi/chapter/updates-retrieving)
|
||||
* Read about [second level](https://bookstack.inmo.dev/books/telegrambotapi/page/updates-with-flows) of working with library
|
||||
* Read about [BehaviourBuilder](https://bookstack.inmo.dev/books/telegrambotapi/page/behaviour-builder)
|
||||
57
docs/tgbotapi/logic/behaviour-builder-with-fsm.md
Normal file
57
docs/tgbotapi/logic/behaviour-builder-with-fsm.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Behaviour Builder with FSM
|
||||
|
||||
Behaviour builder with FSM is based on the MicroUtils FSM. There are several important things in FSM:
|
||||
|
||||
* `State` - any object which implements [State](https://microutils.inmo.dev/micro_utils.dokka/dev.inmo.micro_utils.fsm.common/-state/index.html) interface
|
||||
* `StateHandler` (or [CheckableHandlerHolder](https://microutils.inmo.dev/micro_utils.dokka/dev.inmo.micro_utils.fsm.common/-checkable-handler-holder/index.html)) - the handler of states
|
||||
* [StatesMachine](https://microutils.inmo.dev/micro_utils.dokka/dev.inmo.micro_utils.fsm.common/-states-machine/index.html) - some machine which work with states and handlers
|
||||
* [StatesManager](https://microutils.inmo.dev/micro_utils.dokka/dev.inmo.micro_utils.fsm.common/-states-manager/index.html) - simple manager that will solve which states to save and notify about states changes via its flows
|
||||
|
||||
`StatesMachine` have two methods:
|
||||
|
||||
* `start` which will start work of machine
|
||||
* `startChain` which will add new state for handling
|
||||
|
||||
The most based way to create `StatesMachine` and register `StateHandler`s looks like in the next snippet:
|
||||
|
||||
```kotlin
|
||||
buildFSM<TrafficLightState> {
|
||||
strictlyOn<SomeState> {
|
||||
// state handling
|
||||
}
|
||||
}.start(CoroutineScope(...)).join()
|
||||
```
|
||||
|
||||
> NOTE: **Full example**
|
||||
> You may find full example of FSM usage in [the tests of FSM in MicroUtils](https://github.com/InsanusMokrassar/MicroUtils/blob/master/fsm/common/src/jvmTest/kotlin/PlayableMain.kt)
|
||||
|
||||
|
||||
So, you must do next steps before you will launch your bot with FSM:
|
||||
|
||||
* Create your states. Remember that you may plan to save them, so it is likely you will need to serialize it there
|
||||
* Create your handlers for your states. In most cases it is useful to use [CheckableHandlerHolder](https://microutils.inmo.dev/micro_utils.dokka/dev.inmo.micro_utils.fsm.common/-checkable-handler-holder/index.html) if you want to use standard states machine
|
||||
* Solve which states managers to use (the most simple one is the [DefaultStatesManager](https://microutils.inmo.dev/micro_utils.dokka/dev.inmo.micro_utils.fsm.common.managers/-default-states-manager/index.html) with [InMemoryDefaultStatesManager](https://microutils.inmo.dev/micro_utils.dokka/dev.inmo.micro_utils.fsm.common.managers/-in-memory-default-states-manager-repo/index.html))
|
||||
|
||||
## Bot with FSM
|
||||
|
||||
There are several extensions for `TelegramBot` to create your bot with FSM:
|
||||
|
||||
* [buildBehaviourWithFSM](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.behaviour_builder/build-behaviour-with-f-s-m.html)
|
||||
* [buildBehaviourWithFSMAndStartLongPolling](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.behaviour_builder/build-behaviour-with-f-s-m-and-start-long-polling.html)
|
||||
* [telegramBotWithBehaviourAndFSM](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.behaviour_builder/telegram-bot-with-behaviour-and-f-s-m.html)
|
||||
* [telegramBotWithBehaviourAndFSMAndStartLongPolling
|
||||
](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.behaviour_builder/telegram-bot-with-behaviour-and-f-s-m-and-start-long-polling.html)
|
||||
|
||||
All of them will take as an callback some object with type [CustomBehaviourContextReceiver](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.behaviour_builder/index.html#-1892390839%2FClasslikes%2F-1982836883) and will looks like in the next snippet:
|
||||
|
||||
```kotlin
|
||||
telegramBotWithBehaviourAndFSMAndStartLongPolling<YourStateType>("BOT_TOKEN") {
|
||||
// here you may use any operations from BehaviourBuilder
|
||||
// here you may use any operations from BehaviourContextWithFSMBuilder like strictlyOn and others
|
||||
}
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
* [TelegramBotAPI-examples/FSMBot](https://github.com/InsanusMokrassar/TelegramBotAPI-examples/blob/master/FSMBot/src/main/kotlin/SimpleFSMBot.kt)
|
||||
* [MicroUtils simple example in the tests](https://github.com/InsanusMokrassar/MicroUtils/blob/master/fsm/common/src/jvmTest/kotlin/PlayableMain.kt)
|
||||
68
docs/tgbotapi/logic/behaviour-builder.md
Normal file
68
docs/tgbotapi/logic/behaviour-builder.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# Behaviour Builder
|
||||
|
||||
In the previous pages about [updates handling](https://bookstack.inmo.dev/books/telegrambotapi/page/updates-with-flows) and was mentioned that currently in the most cases you should use [Flow](https://kotlinlang.org/docs/flow.html)s. So, there is an improvement for that system which hide direct work with flows and allow you to create more declarative logic of your bot.
|
||||
|
||||
## Main parts of Behaviour Builder
|
||||
|
||||
There are several things you should know for better understanding of behaviour builder:
|
||||
|
||||
* [BehaviourContext](https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/tgbotapi.behaviour_builder/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContext.kt#L33) - it is the thing which contains all necessary tools for working with bots
|
||||
* [Triggers](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling/index.html) - `on*` extensions for `BehaviourContext` which allow you to create reaction on some update
|
||||
* [Expectations](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.behaviour_builder.expectations/index.html) (or waiters) - `wait*` extensions which you **may** use in [buildBehaviour](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.behaviour_builder/build-behaviour.html) function, but ***it is recommended*** to use it in bodies of triggers
|
||||
|
||||
## Initialization
|
||||
|
||||
As was said above, there is [buildBehaviour](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.behaviour_builder/build-behaviour.html) function which allow you set up your bot logic. Let's see an example:
|
||||
|
||||
```kotlin
|
||||
val bot = telegramBot("TOKEN")
|
||||
|
||||
bot.buildBehaviour {
|
||||
onCommand("start") { // creating of trigger
|
||||
val message = it
|
||||
val content = message.content
|
||||
|
||||
reply(message, "Ok, send me one photo") // send text message with replying on incoming message
|
||||
|
||||
val photoContent = waitPhoto().first() // waitPhoto will return List, so, get first element
|
||||
|
||||
val photo = downloadFile(photoContent) // ByteArray of photo
|
||||
|
||||
// some logic with saving of photos
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Filters
|
||||
|
||||
In most cases there are opportunity to filter some of messages before starting of main logic. Let's look at this using the example above:
|
||||
|
||||
```kotlin
|
||||
val bot = telegramBot("TOKEN")
|
||||
|
||||
bot.buildBehaviour {
|
||||
onCommand(
|
||||
"start",
|
||||
initialFilter = {
|
||||
it.content.textSources.size == 1 // make sure that user has sent /start without any additions
|
||||
}
|
||||
) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
OR
|
||||
|
||||
```kotlin
|
||||
val bot = telegramBot("TOKEN")
|
||||
|
||||
bot.buildBehaviour {
|
||||
onCommand(
|
||||
"start",
|
||||
requireOnlyCommandInMessage = true // it is default, but you can overwrite it with `requireOnlyCommandInMessage = false`
|
||||
) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
97
docs/tgbotapi/logic/exceptions-handling.md
Normal file
97
docs/tgbotapi/logic/exceptions-handling.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# Exceptions handling
|
||||
|
||||
Unfortunatelly, exceptions handling in this library is a bit difficult in some places, but that have at least two reasons: flexibility and usability.
|
||||
|
||||
## "In place" handling
|
||||
|
||||
In case you know, where exceptions are happening, you may use several tools for exceptions catching:
|
||||
|
||||
* Catching with result
|
||||
* Catching with callback
|
||||
|
||||
### Catching with result
|
||||
|
||||
If you prefer to receive `Result` objects instead of some weird callbacks, you may use the next syntax:
|
||||
|
||||
```kotlin
|
||||
safelyWithResult {
|
||||
// do something
|
||||
}.onSuccess { // will be called if everything is right
|
||||
// handle success
|
||||
}.onFailure { // will be called if something went wrong
|
||||
// handle error
|
||||
it.printStackTrace()
|
||||
}.getOrThrow() // will return value or throw exception
|
||||
```
|
||||
|
||||
### Catching with callback
|
||||
|
||||
Also there is more simple (in some cases) way to handle exceptions with callbacks:
|
||||
|
||||
```kotlin
|
||||
safely(
|
||||
{
|
||||
// handle error
|
||||
it.printStackTrace()
|
||||
null // return value
|
||||
}
|
||||
) {
|
||||
// do something
|
||||
}
|
||||
```
|
||||
|
||||
### Bonus: different types of handling
|
||||
|
||||
There are two types of handling:
|
||||
|
||||
* Just safely - when you are using something to obviously retrieve value or throw exception. When handling callback has been skipped, it will throw exception by default. For example:
|
||||
```kotlin
|
||||
safely(
|
||||
{
|
||||
it.printStackTrace()
|
||||
"error"
|
||||
}
|
||||
) {
|
||||
error("Hi :)") // emulate exception throwing
|
||||
"ok"
|
||||
} // result will be with type String
|
||||
```
|
||||
* Safely without exceptions - almost the same as `safely`, but this type by default allow to return nullable value (when exception was thrown) instead of just throwing (as with `safely`):
|
||||
```kotlin
|
||||
safelyWithouExceptions {
|
||||
// do something
|
||||
} // will returns nullable result type
|
||||
```
|
||||
|
||||
## Global exceptions handling
|
||||
|
||||
The most simple way to configure exceptions handling is to change `CoroutineContext` when you are creating your `CoroutineScope` for bot processing:
|
||||
|
||||
```kotlin
|
||||
val bot = telegramBot("TOKEN")
|
||||
|
||||
bot.buildBehaviour (
|
||||
scope = scope,
|
||||
defaultExceptionsHandler = {
|
||||
it.printStackTrace()
|
||||
}
|
||||
) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
OR
|
||||
|
||||
```kotlin
|
||||
val bot = telegramBotWithBehaviour (
|
||||
"TOKEN",
|
||||
scope = scope,
|
||||
defaultExceptionsHandler = {
|
||||
it.printStackTrace()
|
||||
}
|
||||
) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Here we have used `ContextSafelyExceptionHandler` class. It will pass default handling of exceptions and will call the block in most cases when something inside of your bot logic has thrown exception.
|
||||
162
docs/tgbotapi/logic/files-handling.md
Normal file
162
docs/tgbotapi/logic/files-handling.md
Normal file
@@ -0,0 +1,162 @@
|
||||
# Files handling
|
||||
|
||||
According to the [documentation](https://core.telegram.org/bots/api#sending-files) there are several ways to work with files:
|
||||
|
||||
* By [FileId](https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/abstracts/InputFile.kt#L52)
|
||||
* By [FileUrl](https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/abstracts/InputFile.kt#L56) (`typealias` for the `FileId`)
|
||||
* By some [MultipartFile](https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/abstracts/InputFile.kt#L74) (in Telegram Bot API it is multipart requests)
|
||||
|
||||
# Files receiving
|
||||
|
||||
There are several cases you may need in your app to work with files:
|
||||
|
||||
* Save `FileId` (for sending in future)
|
||||
* Download some file into memory/file in filesystem
|
||||
|
||||
### Where to get File id or url?
|
||||
|
||||
The most simple way to send some file is to get file id and send it. You may get file id from any message with media. For example, if you have received some [Message](https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/abstracts/Message.kt#L12), you may use [asCommonMessage](https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/tgbotapi.utils/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/utils/ClassCasts.kt#L1094) conversation to be able to get its `content` and then convert it to some content with media. Full code here:
|
||||
|
||||
```kotlin
|
||||
val message: Message;
|
||||
|
||||
val fileId = message.asCommonMessage() ?.withContent<MediaContent>() ?.content ?.media ?.fileId;
|
||||
```
|
||||
|
||||
**WAT? O.o**
|
||||
|
||||
In the code above we get some message, safely converted it to `CommonMessage` with `asCommonMessage`, then safely took its content via `withContent<MediaContent>() ?.content` and then just get its media file id.
|
||||
|
||||
## Download files
|
||||
|
||||
There are three ways to download files:
|
||||
|
||||
* Download it in memory as `ByteArray`
|
||||
* Take `ByteReadChannelAllocator` which allow to retrieve [ByteReadChannel](https://api.ktor.io/ktor-io/io.ktor.utils.io/-byte-read-channel/index.html) and do whatever you want with it
|
||||
* `[JVM Only]` Download it directly to file or temporal file
|
||||
|
||||
### Downloading with `API` extensions
|
||||
|
||||
#### Files (JVM/Android)
|
||||
|
||||
```kotlin
|
||||
val bot: TelegramBot;
|
||||
val fileId: FileId;
|
||||
val outputFile: File;
|
||||
|
||||
bot.downloadFile(fileId, outputFile)
|
||||
```
|
||||
|
||||
See [downloadFile](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.api.files/download-file.html) extension docs in the __JVM tab__ to get more available options
|
||||
|
||||
There is also way with saving of data into temporal file. That will allow you to do with data whatever you want without high requirements to memory or network connection:
|
||||
|
||||
```kotlin
|
||||
val bot: TelegramBot;
|
||||
val fileId: FileId;
|
||||
|
||||
val tempFile: File = bot.downloadFileToTemp(fileId)
|
||||
```
|
||||
|
||||
See [downloadFileToTemp](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.api.files/download-file-to-temp.html) extension docs to get more available options
|
||||
|
||||
#### Byte read channel
|
||||
|
||||
```kotlin
|
||||
val bot: TelegramBot;
|
||||
val fileId: FileId;
|
||||
|
||||
val bytes: ByteReadChannelAllocator = bot.downloadFileStream(fileId)
|
||||
```
|
||||
|
||||
See [downloadFileStream](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.api.files/download-file-stream.html) extension docs to get more available options
|
||||
|
||||
#### Byte read channel allocator
|
||||
|
||||
```kotlin
|
||||
val bot: TelegramBot;
|
||||
val fileId: FileId;
|
||||
|
||||
val bytes: ByteReadChannelAllocator = bot.downloadFileStreamAllocator(fileId)
|
||||
```
|
||||
|
||||
See [downloadFileStreamAllocator](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.api.files/download-file-stream-allocator.html) extension docs to get more available options
|
||||
|
||||
#### Byte arrays
|
||||
|
||||
```kotlin
|
||||
val bot: TelegramBot;
|
||||
val fileId: FileId;
|
||||
|
||||
val bytes: ByteArray = bot.downloadFile(fileId)
|
||||
```
|
||||
|
||||
See [downloadFile](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.api.files/download-file.html) extension docs to get more available options
|
||||
|
||||
### Low level or `how does it work?`
|
||||
|
||||
You may download file with streams or with downloading into the memory first. On low level you should do several things. They are presented in next snippet:
|
||||
|
||||
```kotlin
|
||||
val bot: TelegramBot;
|
||||
val fileId: FileId;
|
||||
|
||||
val pathedFile: PathedFile = bot.execute(GetFile(fileId))
|
||||
|
||||
val downloadedBytes: ByteArray = bot.execute(DownloadFile(pathedFile.filePath))
|
||||
```
|
||||
|
||||
In the snippet above we are getting file `PathedFile` by its `FileId` and use it to download file bytes into memory using `DownloadFile` request.
|
||||
|
||||
You may use almost the same way but with byte read channel allocator:
|
||||
|
||||
```kotlin
|
||||
val bot: TelegramBot;
|
||||
val fileId: FileId;
|
||||
|
||||
val pathedFile: PathedFile = bot.execute(GetFile(fileId))
|
||||
|
||||
val channelAllocator: ByteReadChannelAllocator = bot.execute(DownloadFileStream(pathedFile.filePath))
|
||||
|
||||
val byteReadChannel: ByteReadChannel = channelAllocator()
|
||||
```
|
||||
|
||||
And then you may look into [ByteReadChannel](https://api.ktor.io/ktor-io/io.ktor.utils.io/-byte-read-channel/index.html) docs to get more info about what you can do with that.
|
||||
|
||||
> NOTE: **Several useful links**
|
||||
>
|
||||
> * [GetFile]("https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.requests.get/-get-file/index.html")
|
||||
> * [PathedFile]("https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.types.files/-pathed-file/index.html")
|
||||
> * [DownloadFile]("https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.requests/-download-file/index.html")
|
||||
> * [DownloadFileStream]("https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.requests/-download-file-stream/index.html")
|
||||
|
||||
|
||||
# Files sending
|
||||
|
||||
Of course, in most cases you must be sure that file have correct type.
|
||||
|
||||
## FileId and FileUrl
|
||||
|
||||
It is the most simple way to send any media in Telegram, but this way have several restrictions:
|
||||
|
||||
* The `FileId` which has retrieved for file should not (and probably will not too) equal to the `FileId` retrieved by some other bot
|
||||
* There is a chance that the file id you are using will be expired with time
|
||||
|
||||
## Sending via file
|
||||
|
||||
> WARNING: **JS Restrictions**
|
||||
> Sending via file is accessible from all supported platforms, but there is small note about `JS` - due to restrictions of work with streams and stream-like data (`JS` have no native support of files streaming) on this platform all the files will be loaded inside of RAM before the sending to the telegram services.
|
||||
|
||||
|
||||
Sending via file is available throw the [MultipartFile](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.requests.abstracts/-multipart-file/index.html). There are several wayt to get it:
|
||||
|
||||
* Simple creating via its constructor: `MultipartFile("filename.jpg") { /* here Input allocation */ }`
|
||||
* Via [asMultiparFile](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.requests.abstracts/as-multipart-file.html) extension applicable to any `ByteArray`, `ByteReadChannel`, `ByteReadChannelAllocator` or `File` (on any platform)
|
||||
|
||||
In most cases, sending via files looks like in the next snippet:
|
||||
|
||||
```kotlin
|
||||
val file: File;
|
||||
|
||||
bot.sendDocument(chatId, file.asMultipartFile())
|
||||
```
|
||||
27
docs/tgbotapi/logic/low-level-work-with-bots.md
Normal file
27
docs/tgbotapi/logic/low-level-work-with-bots.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Low-level work with bots
|
||||
|
||||
The base version of library was done a lot of time ago and just got several additions related to improvements, updates in [Telegram Bot API](https://core.telegram.org/bots/api) or some requests from [our community](https://t.me/InMoTelegramBotAPIChat).
|
||||
|
||||
# Base things
|
||||
|
||||
There are several important things in context of this library:
|
||||
|
||||
* [RequestsExecutor](https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/bot/RequestsExecutor.kt#L13) (also "known" as `TelegramBot`)
|
||||
* [Types](https://github.com/InsanusMokrassar/TelegramBotAPI/tree/master/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types)
|
||||
* [Requests](https://github.com/InsanusMokrassar/TelegramBotAPI/tree/master/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests)
|
||||
|
||||
So, in most cases all your request calls with simplified api of this library (like `bot.getMe()`) will looks like `bot.execute(GetMe)`. Result of these calls is defined in type of any request (for example, for [GetMe](https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/bot/GetMe.kt) request the result type is [ExtendedBot](https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/chat/Extended.kt#L101)). As a result, you can avoid any extension api (like [special API extensions](api-extensions.html)) and use low level request with full controlling of the whole logic flow.
|
||||
|
||||
## How to handle updates
|
||||
|
||||
As was written above, it will require some request:
|
||||
|
||||
```kotlin
|
||||
val updates = bot.execute(GetUpdates())
|
||||
```
|
||||
|
||||
Result type of [GetUpdates](https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/requests/GetUpdates.kt#L24) request is [Update](https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/update/abstracts/Update.kt#L13). You may find _inheritors_ of this interface in [Update kdocs](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.types.update.abstracts/-update/index.html).
|
||||
|
||||
## What is next?
|
||||
|
||||
As was said above, you may look into our [API extensions](api-extensions.html) in case you wish to use more high-level functions instead of `bot.execute(SomeRequest())`. Besides, it will be very useful to know more about [updates retrieving](../updates).
|
||||
45
docs/tgbotapi/logic/media-groups.md
Normal file
45
docs/tgbotapi/logic/media-groups.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Media Groups
|
||||
|
||||
As you know, Telegram have the feature named Media Groups. Media groups have several differences with the common messages:
|
||||
|
||||
* Each media group message contains special media group id
|
||||
* Media group may have special caption which will be visible if only the first message of media group contains caption
|
||||
* In most cases media groups came with long polling/webhooks in one pack
|
||||
* Media groups can be one of three types:
|
||||
* Visual (image/video)
|
||||
* Documents
|
||||
* Playlists (audio)
|
||||
|
||||
## Specific of media groups in libraries
|
||||
|
||||
> NOTE: **Row updates**
|
||||
> In tgbotapi there is no any additional handling of media groups by default and in case you will use simple [bot.getUpdates](https://insanusmokrassar.github.io/TelegramBotAPI/docs/dev.inmo.tgbotapi.extensions.api/get-updates.html), you will get the list of row updates and media groups will be included in this list as separated messages with [MediaGroupPartContent](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.types.message.content/-media-group-part-content/index.html). In that case you may use [convertWithMediaGroupUpdates](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.utils.updates/convert-with-media-group-updates.html) to be able to work with media groups as will be described below
|
||||
|
||||
|
||||
In case you are using standard [long polling](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.utils.updates.retrieving/long-polling.html) (one of alternatives is [telegramBotWithBehaviourAndLongPolling](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.behaviour_builder/telegram-bot-with-behaviour-and-long-polling.html)) or [webhooks](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.utils.updates.retrieving/set-webhook-info-and-start-listen-webhooks.html) updates will be converted uner the hood and as a result, you will take media groups as a content in one message:
|
||||
|
||||
```kotlin
|
||||
telegramBotWithBehaviourAndLongPolling(
|
||||
"token"
|
||||
) {
|
||||
onVisualGallery { // it: CommonMessage<MediaGroupContent<VisualMediaGroupPartContent>>
|
||||
it.content // MediaGroupContent<VisualMediaGroupPartContent>
|
||||
it.content.group // List<MediaGroupCollectionContent.PartWrapper<VisualMediaGroupPartContent>>
|
||||
it.content.group.forEach { // it: MediaGroupCollectionContent.PartWrapper<VisualMediaGroupPartContent>
|
||||
it.messageId // source message id for current media group part
|
||||
it.sourceMessage // source message for current media group part
|
||||
it.content // VisualMediaGroupPartContent
|
||||
println(it.content) // will print current content part info
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**KDocs:**
|
||||
|
||||
* [onVisualGallery](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling/on-visual-gallery-messages.html)
|
||||
* [MediaGroupContent](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.types.message.content/-media-group-content/index.html)
|
||||
* [VisualMediaGroupPartContent](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.types.message.content/-visual-media-group-part-content/index.html)
|
||||
* [MediaGroupCollectionContent.PartWrapper](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.types.message.content/-media-group-collection-content/-part-wrapper/index.html)
|
||||
|
||||
In two words, in difference with row Telegram Bot API, you will take media groups in ___one message___ instead of ___messages list___.
|
||||
40
docs/tgbotapi/logic/types-conversations.md
Normal file
40
docs/tgbotapi/logic/types-conversations.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Types conversations
|
||||
|
||||
One of the most important topics in context of tgbotapi is types conversations. This library is very strong-typed and a lot of things are based on types hierarchy. Lets look into the hierarchy of classes for the [Message](https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/message/abstracts/Message.kt#L12) in 0.35.8: [](https://bookstack.inmo.dev/uploads/images/gallery/2021-09/message-diagram.png)
|
||||
|
||||
As you may see, it is a little bit complex and require several tools for types conversation.
|
||||
|
||||
## As
|
||||
|
||||
`as` conversations will return new type in case if it is possible. For example, when you got `Message`, you may use `asContentMessage` conversation to get message with `content`:
|
||||
|
||||
```kotlin
|
||||
val message: Message;
|
||||
println(message.asContentMessage() ?.content)
|
||||
```
|
||||
|
||||
This code will print `null` in case when `message` is not `ContentMessage`, and `content` when is.
|
||||
|
||||
## Require
|
||||
|
||||
`require` works like `as`, but instead of returning nullable type, it will always return object with required type OR throw `ClassCastException`:
|
||||
|
||||
```kotlin
|
||||
val message: Message;
|
||||
println(message.requireContentMessage().content)
|
||||
```
|
||||
|
||||
This code will throw exception when message is not `ContentMessage` and print `content` when is.
|
||||
|
||||
## When
|
||||
|
||||
`when` extensions will call passed `block` when type is correct. For example:
|
||||
|
||||
```kotlin
|
||||
val message: Message;
|
||||
message.whenContentMessage {
|
||||
println(it.content)
|
||||
}
|
||||
```
|
||||
|
||||
Code placed above will print `content` when `message` is `ContentMessage` and do nothing when not
|
||||
57
docs/tgbotapi/logic/updates-with-flows.md
Normal file
57
docs/tgbotapi/logic/updates-with-flows.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Updates with flows
|
||||
|
||||
Of course, in most cases here we will look up the way of using [utils extnsions](https://github.com/InsanusMokrassar/TelegramBotAPI/tree/master/tgbotapi.utils/), but you may read deeper about updates retrieving [here](https://bookstack.inmo.dev/books/telegrambotapi/chapter/updates-retrieving).
|
||||
|
||||
## Phylosophy of `Flow` updates retrieving
|
||||
|
||||
In most updates retrieving processes there are two components: [UpdatesFiler](https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/updateshandlers/UpdatesFilter.kt) and its inheritor [FlowsUpdatesFilter](https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/updateshandlers/FlowsUpdatesFilter.kt#L12). It is assumed, that you will do several things in your app to handle updates:
|
||||
|
||||
* Create your `UpdatesFilter` (for example, with [flowsUpdatesFilter](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.utils.updates/flows-updates-filter.html) factory)
|
||||
* Set it up (in case of `flowsUpdatesFilter` you will set up updates handling in the lambda passed to this factory)
|
||||
* Provide updates to this filter with [filter#asUpdateReceiver](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.updateshandlers/-updates-filter/as-update-receiver.html) object
|
||||
|
||||
Let's look how it works with the factory above:
|
||||
|
||||
```kotlin
|
||||
// Step 1 - create filter
|
||||
val filter = flowsUpdatesFilter {
|
||||
// Step 2 - set up handling. In this case we will print any message from group or user in console
|
||||
messageFlow.onEach {
|
||||
println(it)
|
||||
}.launchIn(someCoroutineScope)
|
||||
}
|
||||
|
||||
// Step 3 - passing updates to filter
|
||||
bot.getUpdates().forEach {
|
||||
filter.asUpdatesReceiver(it)
|
||||
}
|
||||
```
|
||||
|
||||
## Long polling
|
||||
|
||||
Some example with long polling has been described above. But it is more useful to use some factories for it. In this page we will look for simple variant with [TelegramBot#longPolling](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.extensions.utils.updates.retrieving/long-polling.html). So, with this function, your handling of updates will looks like:
|
||||
|
||||
```kotlin
|
||||
val bot = telegramBot("TOKEN")
|
||||
|
||||
bot.longPolling {
|
||||
messageFlow.onEach {
|
||||
println(it)
|
||||
}.launchIn(someCoroutineScope)
|
||||
}.join()
|
||||
```
|
||||
|
||||
This example looks like the example above with three steps, but there are several important things here:
|
||||
|
||||
* You **do not** manage retrieving of updates by hands
|
||||
* `.join()` will suspend your function 😊 `longPolling` function returns `Job` and you may use it to:
|
||||
* `cancel` working of long polling (just call `job.cancel()`)
|
||||
* `join` and wait while the work of `longPolling` will not be completed (it will works infinity if you will not cancel it anywhere)
|
||||
* [FlowsUpdatesFilter](https://tgbotapi.inmo.dev/docs/dev.inmo.tgbotapi.updateshandlers/-flows-updates-filter/index.html) has been created under the hood of `longPolling` function
|
||||
|
||||
## Results and `What is next?`
|
||||
|
||||
As a result you can start listen updates and react on it. Next recommended articles:
|
||||
|
||||
* [Behaviour Builder](https://bookstack.inmo.dev/books/telegrambotapi/page/behaviour-builder) as a variant of asynchronous handling of your bot logic
|
||||
* [FSM variant of Behaviour Builder](https://bookstack.inmo.dev/books/telegrambotapi/page/behaviour-builder-with-fsm)
|
||||
Reference in New Issue
Block a user