Webhooks

In telegram bot API there is an opportunity to get updates via webhooks. In this case you will be able to retrieve updates without making additional requests. Most of currently available methods for webhooks are working on ktor server for JVM. Currently, next ways are available for using for webhooks:

  • Route#includeWebhookHandlingInRoute for ktor server
    • Route#includeWebhookHandlingInRouteWithFlows
  • startListenWebhooks
  • RequestsExecutor#setWebhookInfoAndStartListenWebhooks

setWebhookInfoAndStartListenWebhooks

It is the most common way to set updates webhooks and start listening of them. Example:

val bot = telegramBot(TOKEN)

val filter = flowsUpdatesFilter {
  // ...
}

bot.setWebhookInfoAndStartListenWebhooks(
  8080, // listening port. It is required for cases when your server hidden by some proxy or other system like Heroku
  CIO, // default ktor server engine. It is recommended to replace it with something like `Netty`. More info about engines here: https://ktor.io/servers/configuration.html
  SetWebhook(
    "address.com/webhook_route",
    File("/path/to/certificate").toInputFile(), // certificate file. More info here: https://core.telegram.org/bots/webhooks#a-certificate-where-do-i-get-one-and-how
    40, // max allowed updates, by default is null
    filter.allowedUpdates
  ),
  {
    it.printStackTrace() // optional handling of exceptions
  },
  "0.0.0.0", // listening host which will be used to bind by server
  "subroute", // Optional subroute, if null - will listen root of address
  WebhookPrivateKeyConfig( // optional config of private key. It will be installed in server to use TLS with custom certificate. More info here: https://core.telegram.org/bots/webhooks#a-certificate-where-do-i-get-one-and-how
    "/path/to/keystore.jks",
    "KeystorePassword",
    "Keystore key alias name",
    "KeystoreAliasPassword"
  ),
  scope, // Kotlin coroutine scope for internal transforming of media groups
  filter.asUpdateReceiver
)

If you will use previous example, ktor server will bind and listen url 0.0.0.0:8080/subroute and telegram will send requests to address address.com/webhook_route with custom certificate. Alternative variant will use the other SetWebhook request variant:

SetWebhook(
  "address.com/webhook_route",
  "some_file_bot_id".toInputFile(),
  40, // max allowed updates, by default is null
  filter.allowedUpdates
)

As a result, request SetWebhook will be executed and after this server will start its working and handling of updates.

startListenWebhooks

This function is working almost exactly like previous example, but this one will not set up webhook info in telegram:

val filter = flowsUpdatesFilter {
  // ...
}

startListenWebhooks(
  8080, // listening port. It is required for cases when your server hidden by some proxy or other system like Heroku
  CIO, // default ktor server engine. It is recommended to replace it with something like `Netty`. More info about engines here: https://ktor.io/servers/configuration.html
  {
    it.printStackTrace() // optional handling of exceptions
  },
  "0.0.0.0", // listening host which will be used to bind by server
  "subroute", // Optional subroute, if null - will listen root of address
  WebhookPrivateKeyConfig( // optional config of private key. It will be installed in server to use TLS with custom certificate. More info here: https://core.telegram.org/bots/webhooks#a-certificate-where-do-i-get-one-and-how
    "/path/to/keystore.jks",
    "KeystorePassword",
    "Keystore key alias name",
    "KeystoreAliasPassword"
  ),
  scope, // Kotlin coroutine scope for internal transforming of media groups
  filter.asUpdateReceiver
)

The result will be the same as in previous example: server will start its working and handling of updates on 0.0.0.0:8080/subroute. The difference here is that in case if this bot must not answer or send some requiests - it will not be necessary to create bot for receiving of updates.

Extensions includeWebhookHandlingInRoute and includeWebhookHandlingInRouteWithFlows

For these extensions you will need to start your server manualy. In common case it will look like:

val scope = CoroutineScope(Dispatchers.Default)

val filter = flowsUpdatesFilter {
  // ...
}

val environment = applicationEngineEnvironment {
  module {
    routing {
      includeWebhookHandlingInRoute(
        scope,
        {
          it.printStackTrace()
        },
        filter.asUpdateReceiver
      )
    }
  }
  connector {
    host = "0.0.0.0"
    port = 8080
  }
}

embeddedServer(CIO, environment).start(true) // will start server and wait its stoping

In the example above server will started and binded for listening on 0.0.0.0:8080.

See also