Telegraf Telegraf Versions Save

Modern Telegram Bot Framework for Node.js

v4.12.2

1 year ago
  • Fix: session reference counter had defaulted to 0, therefore permanently being cached and never being cleaned up β€” this has been fixed.

v4.12.1

1 year ago
  • Fix: bot.command did not match bot usernames if the registered username was not lowercased (#1809)

v4.12.0

1 year ago

Normally the most exciting features of a new release would be support for the latest Bot API. But in this update, it's session! This has been in the works for many months, and we're happy to bring it to you this release!

πŸ”’ Stable and safe session

Some of you may know that builtin session has been deprecated for quite a while. This was motivated by the fact that session is prone to race-conditions (#1372). This left the community in a grey area where they continued to use session despite the deprecation, since no clear alternative was provided. Added to this was the fact that there were no official database-backed sessions, and all unofficial async session middleware were affected by #1372.

This release finally addresses both of these long-running issues.

πŸƒπŸΌ No more race conditions

#1713 provides a reference-counted implementation resistant to race conditions. Session is now no longer deprecated, and can be used safely!

Note: You should read more about how to safely use session in the docs repo.

ℒ️ Official database adapters are here!

We're also happy to announce a revamped @telegraf/sessionβ€”this provides official store implementations for database-backed sessions via Redis, MongoDB, MySQL, MariaDB, PostgreSQL, and SQLite. Just install the drivers necessary for your database, and off you go! Since this package now only provides a store implementation, it's usable with builtin session, and effectively makes all implementations have the same safety as the core package. Check it out!

πŸ†— Default session

Additionally, session now accepts a defaultSession parameter. You no longer need a hacky middleware to do ctx.session ??= { count }.

// 🀒 Old way
bot.use(session());
bot.use((ctx, next) => {
  ctx.session ??= { count: 0 };
  return next();
});

// 😁 New way βœ…
bot.use(session({ defaultSession: () => ({ count: 0 }) }));
πŸ”Ί Bot API 6.5 support
  • Updated Typegram, added the following Markup.button helpers to request a user or chat:
  • Markup.button.userRequest
  • Markup.button.botRequest
  • Markup.button.groupRequest
  • Markup.button.channelRequest
  • Telegram::setChatPermissions and Context::setChatPermissions accept a new parameter for { use_independent_chat_permissions?: boolean } as documented in the API.
πŸ”Ί Bot API 6.4 support
  • Updated Typegram, added the following new methods to class Telegram and Context:
  • editGeneralForumTopic
  • closeGeneralForumTopic
  • reopenGeneralForumTopic
  • hideGeneralForumTopic
  • unhideGeneralForumTopic
  • Context::sendChatAction will automatically infer message_thread_id for topic messages.
  • Fix for 'this' Context of type 'NarrowedContext' is not assignable to method's 'this' of type 'Context<Update>'.
⚑️ RegExp support for commands!

Another long-standing problem was the lack of support for RegExp or case-insensitive command matching. This is here now:

bot.command("hello", ctx => ctx.reply("You sent a case-sensitive /hello"));
bot.command(/^hello$/i, ctx => ctx.reply("You sent a case-insensitive /hELLo"));
✍️ fmt helpers
  • New join fmt helper to combine dynamic arrays into a single FmtString.
import { fmt, bold, join } from "telegraf/format";

// elsewhere
bot.command("/fruits", async ctx => {
  const array = ["Oranges", "Apples", "Grapes"];
  const fruitList = join(array.map(fruit => bold(fruit)), "\n");
  const msg = fmt`Fruits to buy:\n${fruitList}`;
  await ctx.sendMessage(msg);
});
  • Fixed various bugs in fmt helpers, so things like bold(italic("telegraf")) will now work as expected.
πŸŒ€ Persistent chat actions

ctx.sendChatAction is used to send a "typing", or "uploading photo" status while your bot is working on something. But this is cleared after 5 seconds. If you have a longer process, you may want to keep calling sendChatAction in a loop. This new feature adds an API to help with this:

bot.command('/video', async ctx => {
  // starts sending upload_video action
  await ctx.persistentChatAction("upload_video", async () => {
    const data = await getLargeVideoSomehow();
    await ctx.sendVideo(Input.fromBuffer(data));
  }); // all done, stops sending upload_video
});

Thanks to @orimiles5 for raising this pull request (#1804).

Follow Telegraf_JS to receive these updates in Telegram. If you have feedback about this update, please share with us on @TelegrafJSChat!

v4.11.2

1 year ago
  • Fixed types for sendMediaGroup to accept StreamFile.
  • Only send message_thread_id if is_topic_message is true. Telegram sends message_thread_id for reply messages, even if the group doesn't have topics. This caused the bot to throw when ctx.reply was used against reply messages in non-forums.

v4.11.1

1 year ago
  • Fixed an issue where TypeScript was not able to import "telegraf/filters". Top-level filters.{js|d.ts} were missing in package.json "files" array.

v4.11.0

1 year ago
πŸ”Ί Bot API 6.3 support
  • Updated to Typegram 4.1.0 and added the following new methods to Telegram class:
    • createForumTopic
    • editForumTopic
    • closeForumTopic
    • reopenForumTopic
    • deleteForumTopic
    • unpinAllForumTopicMessages
    • getForumTopicIconStickers
  • Added new method shorthands to Context; add message_thread_id implicitly to Context::send* methods.
✨ Filters! ✨

We've added a new powerful feature called filters! Here's how to use them.

// import our filters
import { message, editedMessage, channelPost, editedChannelPost, callbackQuery } from "telegraf/filters";
// you can also use require, like this:
// const { message, editedMessage, channelPost, editedChannelPost, callbackQuery } = require("telegraf/filters");

const bot = new Telegraf(token);

bot.on(message("text"), ctx => {
  // this is a text message update
  // ctx.message.text
});

bot.on(channelPost("video"), ctx => {
  // this is a video channel post update
  // ctx.channelPost.video
});

bot.on(callbackQuery("game_short_name"), ctx => {
  // this is a callback_query game update
  // ctx.callbackQuery.game_short_name
});

This unlocks the ability to filter for very specific update types previously not possible! This is only an initial release, and filters will become even more powerful in future updates.

All filters are also usable from a new method, ctx.has. This is very useful if you want to filter within a handler. For example:

// handles all updates
bot.use(ctx => {
  if (ctx.has(message("text"))) {
    // handles only text messages
    // ctx.message.text;
  } else {
    // handles all other updates
  }
});

Like bot.on, ctx.has also supports an array of update types and filters, even mixed:

// match a message update or a callbackQuery with data present
bot.on(["message", callbackQuery("data")], handler);

if (ctx.has(["message", callbackQuery("data")])) {
  // ctx.update is a message update or a callbackQuery with data present
};
⚠️ Deprecating `bot.on` and `Composer::on` with message types!

As of this release, filtering by message type using bot.on() (for example: "text", "photo", etc.) is deprecated. Don't panic, though! Your existing bots will continue to work, but whenever you can, you must update your message type filters to use the above filters before v5. This is fairly easy to do, like this:

- bot.on("text", handler);
+ bot.on(message("text"), handler);

The deprecated message type behaviour will be removed in v5.

You might be happy, or fairly upset about this development. But it was important we made this decision. For a long time, Telegraf has supported filtering by both update type and message type.

This meant you could use bot.on("message"), or bot.on("text") (text here is a message type, and not an update type, so this was really making sure that update.message.text existed). However, when polls were introduced, this caused a conflict. bot.on("poll") would match both update.poll (update about stopped polls sent by the bot) and update.message.poll (a message that is a native poll). At type-level, both objects will show as available, which was wrong.

Besides, this type of filters really limited how far we could go with Telegraf. That's why we introduced filters, which are way more powerful and flexible!

⚠️ An important reminder

A few updates back, in 4.9.0, we added ctx.send* methods to replace ctx.reply* methods. This is because in v5 the behaviour of ctx.reply* will be to actually reply to the current message, instead of only sending a message.

To start using this behaviour right away, we had also introduced a middleware. We recommend you start using this, so that you're prepared for v5, which is brewing very soon!

import { useNewReplies } from "telegraf/future";

// this will enable ctx.reply throughout the bot to automatically reply to current message
// use ctx.sendMessage and friends to send a message without replying
bot.use(useNewReplies());
Other changes
  • bot.launch is now catchable (#1657)

    Polling errors were previously uncatchable in Telegraf. They are now. Simply attach a catch to bot.launch:

    ot.launch().catch(e => {
    / polling has errored
    );
    
    / You an also use await and try/catch if you're using ESM
    

    Three things to remember:

    • In case you're using bot.launch in webhook mode, it will immediately resolve after setWebhook completes.
    • This now means that bot.launch in polling mode will not resolve immediately. Instead, it will resolve after bot.stop(), or reject when there's a polling error.
    • The bot will not continue running after it errors, even if the error is caught. Before you create a new bot instance and launch it, consider that this error is fatal for a serious reason (for example: network is down, or bot token is incorrect). You may not want to attempt a restart when this happens.

    We previously did not want fatal errors to be caught, since it gives the impression that it's a handleable error. However, being able to catch this is useful when you launch multiple bots in the same process, and one of them failing doesn't need to bring down the process.

    Use this feature with care. :)

  • Format helpers ("telegraf/format") now use template string substitution instead of naively using +=. (Discussion)

Follow Telegraf_JS to receive these updates in Telegram. If you have feedback about this update, please share with us on @TelegrafJSChat!

v4.10.0

1 year ago
  • Brand new formatting helpers! No more awkward escaping.

    import { fmt, bold, italics, mention } from "telegraf/format";
    
    ctx.reply(fmt`
    Ground control to ${mention("Major Tom", 10000000)}
    ${bold`Lock your Soyuz hatch`} and ${italic`put your helmet on`}
    β€” ${link("David Bowie", "https://en.wikipedia.org/wiki/David_Bowie")}
    `);
    

    This also just works with captions!

    ctx.replyWithPhoto(
      file.id,
      { caption: fmt`${bold`File name:`} ${file.name}` },
    );
    
  • Added Input helpers to create the InputFile object.

    import { Telegraf, Input } from "telegraf";
    const bot = new Telegraf(token);
    
    bot.telegram.sendVideo(chatId, Input.fromLocalFile("../assets/cats.mp4"));
    
    bot.telegram.sendDocument(chatId, Input.fromBuffer(buf));
    
    bot.command("cat", ctx => {
      ctx.sendPhoto(Input.fromURL("https://funny-cats.example/cats.jpg"))
    });
    

    This helps clear the confusion many users have about InputFile.

  • Deprecated ctx.replyWithMarkdown; prefer MarkdownV2 as Telegram recommends.

  • Deprecated ctx.replyWithChatAction; use identical method ctx.sendChatAction instead.

  • bot.launch()'s webhook options now accepts certificate for self-signed certs.

  • Fix bot crashes if updateHandler throws (#1709)

v4.9.2

1 year ago
  • Fixed bad shorthand for ctx.replyWithVideo (#1687)

v4.9.1

1 year ago
  • Updated typegram to v3.11.0.

v4.9.0

1 year ago

You can now follow Telegraf releases on Telegram

  • Added support for Bot API 6.1, and API 6.2.
  • Easier Webhooks! Added Telegraf::createWebhook which calls setWebhook, and returns Express-style middleware. [Example]
  • New docs! at feathers-studio/telegraf-docs. All examples were moved there and updated to full TS and ESM.
  • More type exports: Experimental export of internal types (such as the Extra* types) now found as: import type { Convenience } from "telegraf/types" (#1659)
  • Actual replies: New middleware: import { useNewReplies } from telegraf/future that changes the behaviour of Context::reply* methods to actually reply to the context message. This will be the default in v5.
  • Added Context::sendMessage and Context:sendWith* methods to replace the old Context::reply and Context::replyWith* methods.
  • Updated Telegraf binary! Supports ESM modules, new command-line options --method and --data to call API methods from the command-line.