npm telegraf 4.0.0
v4.0

latest releases: 4.16.3, 4.16.2, 4.16.1...
3 years ago

Changelog Telegraf 4.0

General

  • Port to TypeScript
  • Update to Bot API 5.0
  • Scenes now live in their own namespace called Scenes
  • Allow cancelling requests via AbortController
  • Add attachmentAgent option to provide an agent that is used for fetching files from the web before they are sent to Telegram (previously done through the same agent as used to connect to Telegram itself)

Apart from updating Telegraf to full Telegram Bot API 5.0 support, the most significant improvement is that we now have a code base that is written 100 % in TypeScript, which more or less required a rewrite of the complete library.
Previously, the library was written in JavaScript and had a few type annotations to the side, but they were often incorrect or missing.

In working on the 4.0 release, we created type coverage of the complete Telegram Bot API.
The benefit is that your editor can now autocomplete accross every single field in every single method or entity.
Those who ever tried it out can confirm that this improves the development experience by an order of magnitude.

Note that this update brings 9 months worth of improvements, so while we did our best to summarise all important changes, it's possible that we forgot some!

Composer

  • Add Composer.guard
  • Deprecate static Composer.mount, prefer static Composer.on
  • Make Composer.entity and Composer.match private
  • Remove Composer.catchAll and Composer.safePassThru
  • Catch errors of both branches of Composer.fork
  • Listen to forwards using on('forward_date'), no longer on('forward')

Context

  • Make ctx.botInfo required, i.e. is is always available
  • Make ctx.state readonly
  • Add ctx.senderChat, ctx.unpinAllChatMessages, and ctx.copyMessage
  • ctx.deleteMessage no longer works for edited messages, channel posts, or edited channel posts
  • Remove ctx.updateSubTypes

Extra

Extra is removed entirely, see #1076.
You can now just specify any options directly, without having to create an Extra instance before.

Markup

Markup is largely reworked.
Please check out the new documentation about Markup, this is much easier than trying to understand the differences between the old and the new version.
The TypeScript autocompletion should help you a lot in case you have to change something about your code.

The main thing to watch out for is that all buttons (keyboard buttons and inline buttons) are now created via Markup.button.url and its siblings, no longer via Markup.urlButton.

The integration with Extra is removed.

Session

Remove the ability to specify a custom property on the context object under which the session lives, in other words, the session data can only be available under ctx.session.
Note that this also applies to scene sessions, they now exclusively live under ctx.scene.session.

When no session data is stored, ctx.session is now undefined instead of {}.

Telegraf

Bots should now always be started using bot.launch with the corresponding configuration for either long polling (default) or webhooks.

  • startPolling and startWebhook are now private
  • TimeoutError is now thrown if update takes longer than handlerTimeout to process
  • handlerTimeout defaults to 90 seconds
  • stop returns void and takes reason instead of callback as as an argument
  • channelMode is removed

Polling

  • Remove retryAfter option (used in an error case), always using 5 seconds now
  • Remove timeout option, always using 50 seconds now
  • Remove limit option, always fetching 100 updates now
  • Remove stopCallback option

Common typing issues

Naturally, if your editor validates your code against the TypeScript types, you may find a few bugs here and there that you were not aware of.
Here are a few things you might come across and that we'd like to explain.

Property X is not available for messages, callback queries, etc

This happens in various different forms, one example is this:

bot.on("message", (ctx) => {
  const text = ctx.message.text;
  //                       ^ error here!
  // Property 'text' does not exist on type ...
});

We are listening for messages here, but not all messages are text messages!
As a result, the text property might be absent, for example for photo messages.

Here is how you solve it:

bot.on("message", (ctx) => {
  if ("text" in message) {
    // now we know that we have a text message!
    const text = ctx.message.text; // works!
    console.log(text);
  }
});

Remember that you can always just do this instead:

bot.on("text", (ctx) => {
  // we already know that we have a text message!
  const text = ctx.message.text; // works!
  console.log(text);
});

Cannot access ctx.session or ctx.scene or ctx.wizard type

If you are using sessions, scenes, wizards, or even yet another of the many modules that work with Telegraf, you have to define your own context object.
This context object must specify which types your middleware registers on the context.
We cannot infer this automatically.

This is best explained by an example bot.

Here is one that's relevant: https://github.com/telegraf/telegraf/blob/develop/docs/examples/example-bot.ts

Scenes have various examples here: https://github.com/telegraf/telegraf/tree/develop/docs/examples/scenes

I see a really complicated type error message!

Middleware in Telegraf is very flexible, so we have to do some really fancy stuff under the hood when we infer the types for you.
Whenever you type bot.on(['callback_query', 'text'], (ctx) => ctx.|, and autocomplete shows up, we have to look at the first argument of bot.on, iterate through the array, look at each string in it, and then do a type transformation on the complete Bot API surface to filter out which options are even available on the relevant context objects at this point.
All of this computation happens on the type level.
(Fun fact: in the first iteration of this feature it took up to 20 seconds for autocomplete to show up.)

The point is: types are hard.
It was our main priority to make the types correct, and then we focused on making the type inference fast.
We would love to make TypeScript print more readable type errors, and we are actively looking trying a few things to do this without too much black magic.

Until then, don't give up!
Here's what you can do:

  1. Remember that most type errors come from typos in variable names or other tiny mistakes.
    Double check this first, the problem may be simpler than you thought.
  2. Even complex error messages have parts in them that you understand!
    Look out for these parts, they often help to fix the problem.
  3. The community can help you.
    Don't hesitate to share a code snippet in the Telegram group.
    You are probably not the only one with this problem.

Don't miss a new telegraf release

NewReleases is sending notifications on new releases.