Skip to content

Useful utilities and tips

Jey edited this page Jan 30, 2024 · 8 revisions

Operating with ProcessedUpdate

The ProcessedUpdate is a generic class for updates which, depending on the original data, can be provided in different types (MessageUpdate, CallbackQueryUpdate, etc.)

So you can check the type of incoming data and further manipulate certain data with smartcasts, for example:

// ...
if (update !is MessageUpdate) {
    message { "Only messages are allowed" }.send(user, bot)
    return
}
// Further on, ProcessedUpdate will be perceived as MessageUpdate.

There's also an UserReference interface inside that lets you determine if there's a user reference inside, example use case:

val user = if(update is UserReference) update.user else null

If needed inside there is always the original update in the update parameter.

Dependency injection

The library uses simple mechanism to initialize classes where your update processing methods are annotated with the provided annotations.

ClassManagerImpl is used by default to invoke annotated methods.

But if you want to use some other libraries for that you can redefine the ClassManager interface,
using your preferred mechanism and pass it on when initializing the bot.

fun main() = runBlocking {
    val bot = TelegramBot("BOT_TOKEN", "com.example.controllers") {
        classManager = ClassManagerImpl()
    }

    bot.handleUpdates()
}

Filtering updates

The documentation mentions that you can implement update filtering yourself.

Yes, this is true, it is not done in the library itself because it can be done very easily by yourself and not to complicate the internal logic for those who do not need this functionality.

There's simple example how can it be done:

// function where updates filtering condition defined
fun filteringFun(update: Update): Boolean = update.message?.text.isNullOrBlank()

fun main() = runBlocking {
  val bot = TelegramBot("BOT_TOKEN")

  // setting more specific processing flow for updates
  bot.update.setListener {
    if(filteringFun(it)) return@setListener

    // so simply, if the listener left the scope before reaching the handler function, that it is filtering.
    // actually you can even write directly if-condition there with return@setListener or extend filtering to separate class.

    handle(it) // or manual handling way with block
  }
}

Exception handling

Exceptions received during activities invocation are put into caughtExceptions channel and handler can be attached to them.

There's example of using handler:

fun main() = runBlocking {
    val bot = TelegramBot("BOT_TOKEN")

    launch(Dispatchers.Unconfined) {
        for (e in bot.update.caughtExceptions) {
            // there you have exception and update that caused it, you can pass it to your handler there
            delay(100)
        }
    }
    bot.handleUpdates()
}
Clone this wiki locally