telegraf: Awaiting for telegraf.launch() stops the code.

Context

Trying to await for the bot to launch stops the code. I think this is done so that the code does not close after the bot is launched, but my code requires waiting for the bot to connect for the rest code to work. Is there any better way of doing so? It worked before with older version of telegraf (4.10.0).

  • Telegraf.js Version: 4.11.2
  • Node.js Version: v18.0.0
  • Operating System: Windows 11

Minimal Example Code Reproducing the Issue

const config = require("./config.json");
const { Telegraf } = require("telegraf");

(async () => {
    const telegraf = new Telegraf(config.telegram.token);
    await telegraf.launch();
    console.log("Telegram started.");
})();

Expected Behavior

“Telegram started.” in console.

Current Behavior

Nothing

Error Message and Logs (export DEBUG='telegraf:*')

  telegraf:main Created a `Telegraf` instance +0ms
  telegraf:main Connecting to Telegram +2ms
  telegraf:client HTTP call getMe {} +0ms
  telegraf:main Launching @<botname>_bot +443ms
  telegraf:client HTTP call deleteWebhook { drop_pending_updates: undefined } +442ms
  telegraf:main Bot started with long polling +85ms // Holds there cause of awaiting at telegraf.ts:267 line
  telegraf:polling Starting long polling +0ms
  telegraf:client HTTP call getUpdates { timeout: 50, offset: 0, allowed_updates: [] } +86ms

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 8
  • Comments: 15 (4 by maintainers)

Commits related to this issue

Most upvoted comments

Please update the documentation. Spent quite a lot of time before found out that promise is never resolved by design…

You could also do this:

bot.botInfo = await bot.telegram.getMe();
console.log("Bot started");
bot.launch();

This will prevent launch() from calling getMe on its own, and has all the same guarantees pre-4.11.0 had.

Thanks for opening this issue.

Since 4.11 (4.11.0 release notes: see “Other changes”), we made a choice to make bot.launch() throw error if long polling errors (related: #1657). This would unfortunately mean that the promise never resolves until the bot stops.

We’re aware that although the previous behaviour was undocumented, many users have relied on it to get a “bot started” event. I’m holding off on “fixing” this prematurely by rolling back, so that we can still provide a way for errors to be caught. Meanwhile, you can do this:

const config = require("./config.json");
const { Telegraf } = require(https://github.com/telegraf/telegraf);

(async () => {
    const telegraf = new Telegraf(config.telegram.token);
    console.log("Telegram started.");
    await telegraf.launch();
})();

Note that awaiting bot.launch() is not strictly required unless you have a usecase where you need to catch errors. See the release notes for more details.

I’ll leave this issue open until we’ve provided a new solution to both sides.

Here we go! #1949 adds a callback to bot.launch that is called when launching the bot.

bot.launch(() => console.log("Bot is starting!"));

If you pass LaunchOptions, the callback goes after the options.

bot.launch({ dropPendingUpdates: true }, () => console.log("Bot is starting!"));

This is available on npm as a release candidate: 4.16.0-rc.2. Stable release when #1949 is merged.

Thanks! It works, but as you said, I won’t close the problem until you come up with a better solution.

I solved the problem, for me this solution is suitable. Telegraf@4.14.0

const bot = new Telegraf(process.env.TOKEN);
bot.launch();
// Started message
if (bot) bot.telegram.getMe().then((res) => console.log(`Bot started on https://t.me/${res.username}`))

I hope, I solved your question.

> npm install telegraf@4.10.0

added 1 package, changed 1 package, and audited 109 packages in 2s

11 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
> node .\a.js         
  telegraf:main Created a `Telegraf` instance +0ms
  telegraf:main Connecting to Telegram +2ms
  telegraf:client HTTP call getMe {} +0ms
  telegraf:main Launching @<botname>_bot +460ms
  telegraf:client HTTP call deleteWebhook { drop_pending_updates: undefined } +460ms
  telegraf:polling Starting long polling +0ms
  telegraf:client HTTP call getUpdates { timeout: 50, offset: 0, allowed_updates: [] } +89ms
  telegraf:main Bot started with long polling +91ms
Telegram started.
> 

@mindrunner

How does this solve the original issue? launch still blocks forever when being awaited which leaves a dangling promise.

bot.launch returning a long-lived promise is intentional, because it’s the only place you can handle polling errors (which are generally fatal and the bot cannot continue, unlike handler errors). It allows #1657 to recover from errors gracefully, for when there are more than the single bot running in the process. The new launch callback solves the problem of wanting to log a message on bot start.

Read https://github.com/telegraf/telegraf/releases/tag/v4.11.0 for more details on why that change was made.

I solved the problem, for me this solution is suitable. Telegraf@4.14.0

const bot = new Telegraf(process.env.TOKEN);
bot.launch();
// Started message
if (bot) bot.telegram.getMe().then((res) => console.log(`Bot started on https://t.me/${res.username}`))

I hope, I solved your question.

I don’t think this works, my test failed at telegraf@4.14.0. I forced the telegraf version to 4.10.0 after read the changelog. I will consider upgrading when this issue closed.