node-telegram-bot-api

repository·master·Indexed 27 days ago

https://github.com/yagop/node-telegram-bot-api

A runtime-agnostic TypeScript client (v2) for the Telegram Bot API. Designed for high performance across Node.js, Bun, Deno, and serverless edge runtimes like Cloudflare Workers and Vercel Functions. It features a 1:1 mapping of the Telegram Bot API via the Api class, Koa-style middleware, fluent builders for keyboards and rich text, and built-in support for both long polling and webhooks.

Tokens
34.5K
Snippets
66
Records
217
Agent score
92%

What's inside node-telegram-bot-api

  1. Set up Webhooks for various runtimes

    master

    The library provides specialized helpers for different environments to handle Telegram webhooks. Use webhookCallback for Edge/Serverless (Cloudflare, Bun, Deno, Vercel), nextAppWebhook for Next.js App Router, registerExpressWebhook for Express, and startWebhook or createWebhookServer for Node.js servers.

    // Cloudflare Workers / Bun.serve / Deno Deploy / Vercel Edge
    import { Bot, webhookCallback } from "node-telegram-bot-api";
    const bot = new Bot(TOKEN);
    export default {
      fetch: webhookCallback(bot, { secretToken: SECRET }),
    };
    
    // Next.js App Router
    import { Bot, nextAppWebhook } from "node-telegram-bot-api";
    const bot = new Bot(process.env.BOT_TOKEN!);
    export const POST = nextAppWebhook(bot, { secretToken: process.env.SECRET });
    
    // Express
    import express from "express";
    import { Bot, registerExpressWebhook } from "node-telegram-bot-api";
    const app = express();
    const bot = new Bot(TOKEN);
    registerExpressWebhook(bot, app, { path: "/telegram", secretToken: SECRET });
    
    // Self-hosted Node server
    import { Bot } from "node-telegram-bot-api";
    import { createWebhookServer, startWebhook } from "node-telegram-bot-api/node";
    const server = createWebhookServer(new Bot(TOKEN), { path: "/telegram", secretToken: SECRET });
    server.listen(8080);
  2. Use Middleware and Error Boundaries

    master

    The library uses Koa-style middleware. Every update passes through a chain where you can wrap downstream work with await next(). Use bot.catch() to define a custom error boundary for handler errors to prevent them from crashing the bot or being lost.

    // ⏱️ time every update - and catch anything thrown downstream
    bot.use(async (ctx, next) => {
      const start = Date.now();
      try {
        await next();
      } finally {
        console.log(`update took ${Date.now() - start}ms`);
      }
    });
    
    // 🧯 last-resort error handler
    bot.catch((err, ctx) => console.error("handler failed", err));
  3. Upload Files and Media

    master

    To upload files, use InputFile to wrap raw bytes, Blob, or Uint8Array. For Node.js environments, you can use fromPath to upload directly from disk. For replayable streaming uploads (to support retries), pass a factory function to InputFile that returns a fresh stream.

    import { Bot, InputFile, MediaGroupBuilder } from "node-telegram-bot-api";
    import { fromPath } from "node-telegram-bot-api/node";
    
    const bot = new Bot(process.env.BOT_TOKEN!);
    
    // upload from disk (Node only)
    await bot.api.sendPhoto({ chat_id, photo: await fromPath("./cat.jpg") });
    
    // upload raw bytes (web-standard, runs anywhere)
    await bot.api.sendDocument({ chat_id, document: new InputFile(bytes, { filename: "report.pdf" }) });
    
    // replayable streaming upload: the factory opens a new stream per attempt
    await bot.api.sendVideo({
      chat_id,
      video: new InputFile(() => openVideoStream(), { filename: "video.mp4", contentType: "video/mp4" }),
    });
    
    // MediaGroupBuilder: optional sugar for the same array
    await bot.api.sendMediaGroup({
      chat_id,
      media: new MediaGroupBuilder()
        .photo({ media: new InputFile(bytesA, { filename: "a.jpg" }), caption: "A" })
        .photo({ media: "https://telegram.org/example/photo.jpg" })
        .build(),
    });
  4. Configure Rate Limiting in BotOptions

    master

    When configuring a bot via BotOptions or TransportOptions, you can define rateLimit settings using RateLimitOptions to control requests-per-second. Supported tiers include:

    • global: Global requests-per-second limit.
    • maxChatBuckets: Maximum number of concurrent chat buckets.
    • perChat: Requests-per-second limit per individual chat.
  5. Enable debug tracing via environment variables

    master

    The library uses the standard debug convention for tracing. To see internal traces in a Node.js environment, set the DEBUG environment variable to include the library's namespace. All traces are prefixed with node-telegram-bot-api:.

    To enable all traces, use: DEBUG="node-telegram-bot-api:*"

  6. Use runtime-agnostic core vs Node-specific features

    master

    The main entry point (.) is designed to be runtime-agnostic, importing only Web-standard APIs. This makes it compatible with Node 18+, Bun, Deno, Cloudflare Workers, Vercel Edge, and Deno Deploy.

    If you require Node-specific features such as fs uploads, a self-hosted webhook server, or a managed polling runner, you must use the ./node subpath instead of the default import.

  7. Use the Node.js specific entry point for Telegram Bot API

    master

    When working in a Node.js environment, import from node-telegram-bot-api/node instead of the core package. This entry point provides the standard Telegram Bot API functionality plus Node-specific features including:

    • File uploads from local paths via fromPath.
    • A built-in webhook server using node:http.
    • A managed long-polling runner.

    Note: Importing from this subpath enables stderr tracing if the DEBUG environment variable is set.

  8. Debug the request lifecycle, polling, and webhooks

    master

    You can trace the request lifecycle, polling, and webhooks by setting the DEBUG environment variable using the debug convention. Logs are sent to stderr.

    Note: Tracing is only available in Node.js environments (via import 'node-telegram-bot-api/node'). On edge runtimes, this is a no-op.

    Available namespaces:

    • node-telegram-bot-api:transport (request/response lifecycle)
    • node-telegram-bot-api:polling
    • node-telegram-bot-api:webhook

    You can filter by namespace or exclude one using a leading minus (e.g., node-telegram-bot-api:*,-:polling).

    DEBUG="node-telegram-bot-api:*" node app.js
    # node-telegram-bot-api:transport -> sendMessage
    # node-telegram-bot-api:transport <- sendMessage ok +142ms
  9. Basic Bot Usage

    master

    Initialize a Bot instance with your token. You can register handlers for commands, regex patterns, and specific update types (like message or callback_query). Registration order determines priority. Use run(bot) from node-telegram-bot-api/node for a managed runner that handles graceful shutdowns (Ctrl-C).

    import { Bot, InlineKeyboardBuilder } from "node-telegram-bot-api";
    import { run } from "node-telegram-bot-api/node"; // managed runner: wires Ctrl-C to bot.stop()
    
    const bot = new Bot(process.env.BOT_TOKEN!);
    
    // commands, regex and update types are all middleware - registration order wins
    bot.command("start", (ctx) => ctx.reply("Hi! Send me anything."));
    bot.hears(/echo (.+)/, (ctx) => ctx.reply(ctx.match![1]!));
    
    bot.on("message", (ctx) =>
      ctx.reply("Pick one:", {
        reply_markup: new InlineKeyboardBuilder()
          .text("👍", "up")
          .text("👎", "down")
          .build(),
      }),
    );
    
    // 🔘 a tapped inline button comes back as a callback_query
    bot.on("callback_query", async (ctx) => {
      await ctx.answerCallbackQuery({ text: `You tapped ${ctx.callbackQuery!.data}` });
    });
    
    await run(bot); // core-only alternative that runs anywhere: await bot.startPolling()