tgbotapi/tgbotapi.utils
InsanusMokrassar 3997af171e StickerSetName now is value class 2024-03-16 23:07:55 +06:00
..
api StickerSetName now is value class 2024-03-16 23:07:55 +06:00
src StickerSetName now is value class 2024-03-16 23:07:55 +06:00
README.md cleanup 'extension' suffix in readmes 2021-10-18 15:37:10 +06:00
build.gradle cratch fix of build fails 2023-11-25 17:54:40 +06:00

README.md

TelegramBotAPI Util Extensions

Maven Central

What is it?

It is wrapper library for TelegramBotAPI Core. Currently, this library contains some usefull filters for commands, updates types and different others.

How to implement library?

Common ways to implement this library are presented here. In some cases it will require additional steps like inserting of additional libraries (like kotlin stdlib). In the examples will be used variable telegrambotapi-extensions-utils_version, which must be set up by developer. Next version is last published:

Maven Central

Maven

Dependency config presented here:

<dependency>
  <groupId>dev.inmo</groupId>
  <artifactId>tgbotapi.utils</artifactId>
  <version>${telegrambotapi-extensions-utils_version}</version>
</dependency>

Gradle

To use last versions you will need to add one line in repositories block of your build.gradle:

mavenCentral()

And add next line to your dependencies block:

implementation "dev.inmo:tgbotapi.utils:$telegrambotapi-extensions-utils_version"

or for old gradle:

compile "dev.inmo:tgbotapi.utils:$telegrambotapi-extensions-utils_version"

How to use?

Here will be presented several examples of usage. In all cases it is expected that you have created your bot and filter:

val bot: RequestsExecutor = KtorRequestsExecutor(
    TelegramAPIUrlsKeeper(BOT_TOKEN)
)
val filter = FlowsUpdatesFilter(64)

Alternative way to use the things below:

val filter = bot.startGettingFlowsUpdatesByLongPolling(
    scope = CoroutineScope(Dispatchers.Default)
) {
    // place code from examples here with replacing of `filter` by `this`
}

Updates

As mentioned in Telegram Bot API reference, there are two ways for updates retrieving:

  • Webhooks
  • Long Polling

Both of them you could use in your project using TelegramBotAPI Core, but here there are several useful extensions for both of them.

Anyway, in both of ways it will be useful to know that it is possible to create UpdateReceiver object using function flowsUpdatesFilter:

val internalChannelsSizes = 128
flowsUpdatesFilter(internalChannelsSizes/* default is 64 */) {
    textMessages().onEach {
        println("I have received text message: ${it.content}")
    }.launchIn(someCoroutineScope)
    /* ... */
}

Long polling

The most simple way is Long Polling and one of the usages was mentioned above:

val filter = bot.startGettingFlowsUpdatesByLongPolling(
    scope = CoroutineScope(Dispatchers.Default)
) {
    // place code from examples here with replacing of `filter` by `this`
}

Extension startGettingFlowsUpdatesByLongPolling was used in this example, but there are a lot of variations of startGettingOfUpdatesByLongPolling and others for getting the same result. Usually, it is supposed that you already have created filter object (or something like this) and will pass it into extension:

val filter = FlowsUpdatesFilter(64)
bot.startGettingOfUpdatesByLongPolling(
    filter
)

But also there are extensions which allow to pass lambdas directly:

bot.startGettingOfUpdatesByLongPolling(
    {
        println("Received message update: $it")
    }
)

Anyway, it is strictly recommended to pass your CoroutineScope object to this method at least for more comfortable management of updates.

WebHooks (currently JVM-only)

For webhooks there are less number of functions and extensions than for Long Polling (but it is still fully automated):

startListenWebhooks(
    8081,
    CIO // require to implement this engine dependency
) {
    // here will be all updates one by one in $it
}

Besides, there are two additional opportunities:

  • Extension Route#includeWebhookHandlingInRoute, which allow you to include webhook processing inside your ktor application without creating of new one server (as it is happening in startListenWebhooks)
    • Also, you can use Route#includeWebhookHandlingInRouteWithFlows to use it like flowUpdatesFilter fun, but apply FlowsUpdatesFilter to the block
  • Extension RequestsExecutor#setWebhookInfoAndStartListenWebhooks. It is allow to set up full server (in fact, with startListenWebhooks), but also send SetWebhook request before and check that it was successful

Filters

There are several filters for flows.

Updates

In the next table it is supposed that you are using some Flow with type from Base type of update and apply extension Extension and will get Flow with type from Result type of update column.

Base type of update Extension Result type of update
Update onlyBaseMessageUpdates BaseMessageUpdate
BaseMessageUpdate onlySentMessageUpdates BaseSentMessageUpdate
BaseMessageUpdate onlyEditMessageUpdates BaseEditMessageUpdate
BaseMessageUpdate onlyMediaGroupsUpdates MediaGroupUpdate
MediaGroupUpdate onlySentMediaGroupUpdates SentMediaGroupUpdate
MediaGroupUpdate onlyEditMediaGroupUpdates EditMediaGroupUpdate

All of these extensions was made for more simple work with the others:

val flow: Flow<BaseMessageUpdate> = ...; // here we are getting flow from somewhere,
                                        // for example, FlowsUpdatesFilter#messageFlow
flow.onlySentMessageUpdates().filterExactCommands(Regex("start"))

Here we have used filter filterExactCommands which will pass only ContentMessage with only one command start

Sent messages

All sent messages can be filtered for three types:

Type Description Flow extension
Common messages Simple messages with text, media, location, etc. asContentMessagesFlow
Chat actions New chat member, rename of chat, etc. asChatEventsFlow
Unknown events Any other messages, that contain unsupported data asUnknownMessagesFlow
Common messages

Unfortunately, due to the erasing of generic types, when you are using asContentMessagesFlow you will retrieve data with type ContentMessage<*>. For correct filtering of content type for retrieved objects, was created special filters:

Content type Result type Flow extension
Animation ContentMessage<AnimationContent> onlyAnimationContentMessages
Audio ContentMessage<AudioContent> onlyAudioContentMessages
Contact ContentMessage<ContactContent> onlyContactContentMessages
Dice ContentMessage<DiceContent> onlyDiceContentMessages
Document ContentMessage<DocumentContent> onlyDocumentContentMessages
Game ContentMessage<GameContent> onlyGameContentMessages
Invoice ContentMessage<InvoiceContent> onlyInvoiceContentMessages
Location ContentMessage<LocationContent> onlyLocationContentMessages
Photo ContentMessage<PhotoContent> onlyPhotoContentMessages
Poll ContentMessage<PollContent> onlyPollContentMessages
Sticker ContentMessage<StickerContent> onlyStickerContentMessages
Text ContentMessage<TextContent> onlyTextContentMessages
Venue ContentMessage<VenueContent> onlyVenueContentMessages
Video ContentMessage<VideoContent> onlyVideoContentMessages
VideoNote ContentMessage<VideoNoteContent> onlyVideoNoteContentMessages
Voice ContentMessage<VoiceContent> onlyVoiceContentMessages

For example, if you wish to get only photo messages from private chats of groups, you should call next code:

filter.messageFlow.asContentMessagesFlow().onlyPhotoContentMessages().onEach {
    println(it.content)
}.launchIn(
    CoroutineScope(Dispatchers.Default)
)
Chat actions

Chat actions can be divided for three types of events source:

Type Flow extension
Channel events onlyChannelEvents
Group events onlyGroupEvents
Supergroup events onlySupergroupEvents

According to this table, if you want to add filtering by supergroup events, you will use code like this:

filter.messageFlow.asChatEventsFlow().onlySupergroupEvents().onEach {
    println(it.chatEvent)
}.launchIn(
    CoroutineScope(Dispatchers.Default)
)

Shortcuts

With shortcuts you are able to use simple factories for several things.

ScheduledCloseInfo

In case if you are creating some poll, you able to use next shortcuts.

Next sample will use info with closing at the 10 seconds after now:

closePollExactAt(DateTime.now() + TimeSpan(10000.0))

In this example we will do the same, but in another way:

closePollExactAfter(10)

Here we have passed 10 seconds and will get the same result object.

In opposite to previous shortcuts, the next one will create approximate closing schedule:

closePollAfter(10)

The main difference here is that the last one will be closed after 10 seconds since the sending. With first samples will be created exact time for closing of poll