npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

telegrams-node-bot

v1.0.1

Published

Ultra-lightweight, high-performance Telegram Bot framework for low-resource environments

Readme

telegrams-node-bot 🚀

Ultra-lightweight, high-performance Telegram Bot Framework for Node.js

telegrams-node-bot is a minimalist Telegram bot framework designed specifically for low-resource environments. It delivers powerful features while consuming minimal RAM and CPU resources.

npm version License: MIT Node.js Version


📚 Table of Contents


🌟 Why telegrams-node-bot?

Most Telegram bot frameworks are heavy, consuming hundreds of megabytes of RAM and significant CPU resources. telegrams-node-bot is different.

Performance Comparison

| Metric | Traditional Frameworks | telegrams-node-bot | |--------|----------------------|-----------| | RAM Usage | 100-300 MB | 10-30 MB | | Startup Time | 2-5 seconds | < 100ms | | Dependencies | 10-50 packages | 0 dependencies | | Command Lookup | O(n) linear scan | O(1) Map-based | | CPU Usage | High (event loops) | Minimal |

Key Benefits

  • ✅ Zero dependencies — Uses only Node.js built-in APIs
  • ✅ Memory efficient — Bounded queues and automatic cleanup
  • ✅ Fast execution — Map-based O(1) command resolution
  • ✅ TypeScript native — Full type support out of the box
  • ✅ Production ready — Built-in error handling and rate limiting
  • ✅ Mini App support — Secure validation and authentication
  • ✅ Session management — Built-in per-user state tracking
  • ✅ Middleware system — Composable request pipeline

✨ Features

Core Features

  • Lightweight Architecture — Optimized for low-end VPS and shared hosting
  • Fast Command System — O(1) Map-based command lookup
  • Smart Rate Limiting — Protect against spam and abuse
  • Request Queue — Bounded concurrency for API calls
  • Inline Keyboards — Full support with callbacks
  • Reply Keyboards — Custom keyboards with resize options
  • Message Editing — Edit messages and reply markups
  • Payment Support — Telegram Stars and invoices
  • Mini App Integration — Secure initData validation
  • Webhook Support — Both polling and webhook modes
  • Session Store — Built-in per-user state management with TTL
  • Middleware Pipeline — Compose reusable request handlers

Advanced Features

  • Inline Queries — Handle inline mode requests
  • File Uploads — Send photos, documents, and media
  • Chat Actions — Typing indicators and status updates
  • Priority Queue — Prioritize important API calls
  • Error Recovery — Graceful handling of network issues
  • Rate Limit Info — Check remaining requests and reset time

📦 Installation

Prerequisites

  • Node.js 18 or higher
  • npm, yarn, or pnpm

Install

# Using npm
npm install telegrams-node-bot

# Using yarn
yarn add telegrams-node-bot

# Using pnpm
pnpm add telegrams-node-bot

🚀 Quick Start

1. Get Your Bot Token

  1. Open Telegram and search for @BotFather
  2. Send /newbot command
  3. Follow the instructions
  4. Copy your bot token

2. Create Your First Bot

JavaScript (ESM) — bot.js:

import { LiteGram, keyboard, inlineKeyboard } from "telegrams-node-bot";

// Initialize bot
const bot = new LiteGram({
  token: "YOUR_BOT_TOKEN",
  polling: true // Auto-start polling
});

// Handle /start command
bot.command("start", async (ctx) => {
  const name = ctx.from?.first_name || "User";

  await ctx.reply(`Hello ${name}! 👋`, {
    reply_markup: keyboard([
      ["📝 Register", "ℹ️ Info"],
      ["💰 Premium"]
    ])
  });
});

// Handle /menu command
bot.command("menu", async (ctx) => {
  await ctx.reply("Choose an option:", {
    reply_markup: inlineKeyboard([
      [
        { text: "Button 1", callback_data: "btn1" },
        { text: "Button 2", callback_data: "btn2" }
      ],
      [
        { text: "Open Website", url: "https://example.com" }
      ]
    ])
  });
});

// Start bot
bot.start();
console.log("Bot is running...");

TypeScript — bot.ts:

import { LiteGram, keyboard, inlineKeyboard, Context } from "telegrams-node-bot";

const bot = new LiteGram({
  token: "YOUR_BOT_TOKEN",
  polling: true
});

bot.command("start", async (ctx: Context) => {
  await ctx.reply("Welcome to telegrams-node-bot!");
});

bot.start();

3. Run Your Bot

# JavaScript
node bot.js

# TypeScript
npx tsc && node dist/bot.js

🎯 Core Concepts

1. Bot Instance

The LiteGram class is the main entry point:

const bot = new LiteGram({
  token: "YOUR_BOT_TOKEN",              // Required: Bot token from BotFather
  polling: true,                        // Auto-start polling
  timeout: 30,                          // Polling timeout in seconds
  limit: 100,                           // Updates per request
  apiRoot: "https://api.telegram.org",  // Custom API endpoint
  testMode: false                       // Test mode for payments
});

Configuration Options:

| Option | Type | Default | Description | |--------|------|---------|-------------| | token | string | — | Required. Bot token from BotFather | | polling | boolean | false | Auto-start long polling on init | | timeout | number | 30 | Polling timeout in seconds | | limit | number | 100 | Max updates per request | | allowed_updates | string[] | all | Update types to receive | | apiRoot | string | https://api.telegram.org | Custom API endpoint | | testMode | boolean | false | Test mode for payments |


2. Context Object

Every handler receives a ctx (context) object:

bot.command("start", async (ctx) => {
  // User information
  console.log(ctx.from);        // TelegramUser object
  console.log(ctx.chat);        // Chat object
  console.log(ctx.message);     // Message object

  // Response methods
  await ctx.reply("Hello!");    // Send message
  await ctx.replyWithPhoto("https://example.com/photo.jpg");
  await ctx.sendChatAction("typing");
});

Context Properties:

| Property | Type | Description | |----------|------|-------------| | ctx.update | Update | Raw update object | | ctx.from | TelegramUser | User who sent the message | | ctx.chat | TelegramChat | Chat information | | ctx.message | TelegramMessage | Message object | | ctx.callbackQuery | CallbackQuery | Callback query data | | ctx.preCheckoutQuery | PreCheckoutQuery | Payment pre-checkout data | | ctx.successfulPayment | SuccessfulPayment | Successful payment data | | ctx.session | SessionContext | Per-user session storage |

Context Methods:

| Method | Description | |--------|-------------| | ctx.reply(text, options) | Send a message | | ctx.replyWithPhoto(photo, options) | Send a photo | | ctx.editMessageText(options) | Edit message text | | ctx.editMessageReplyMarkup(markup) | Edit inline keyboard | | ctx.deleteMessage() | Delete the current message | | ctx.answerCallbackQuery(text, showAlert) | Answer callback query | | ctx.sendInvoice(options) | Send payment invoice | | ctx.sendStarsInvoice(options) | Send Stars invoice | | ctx.sendChatAction(action) | Send typing/upload action | | ctx.getChat() | Get chat information |


3. Command System

Commands are resolved in O(1) time using Map-based lookup:

// Register command handler
bot.command("start", async (ctx) => {
  await ctx.reply("Starting...");
});

// Multiple commands
bot.command("help", handleHelp);
bot.command("info", handleInfo);
bot.command("settings", handleSettings);

How it works:

  • Commands are stored in a Map keyed by command name
  • Lookup is O(1) instead of O(n) linear scan
  • Command names are case-insensitive and lowercased automatically

4. Event Handlers

Handle different types of updates:

// Message handler (all text messages)
bot.on("message", async (ctx) => {
  console.log(ctx.message?.text);
});

// Callback query handler
bot.on("callback_query", async (ctx) => {
  const data = ctx.callbackQuery?.data;
  await ctx.answerCallbackQuery(`You clicked: ${data}`);
});

// Inline query handler
bot.on("inline_query", async (ctx) => {
  // Handle inline queries
});

Supported Events:

| Event | Description | |-------|-------------| | message | Text messages and media | | callback_query | Inline button clicks | | inline_query | Inline mode queries | | edited_message | Edited messages | | channel_post | Channel posts |


5. Session Management

telegrams-node-bot includes a built-in Session Store for per-user state:

bot.command("register", async (ctx) => {
  // Save session state
  ctx.session.set({ step: "waiting_name" });
  await ctx.reply("What's your name?");
});

bot.on("message", async (ctx) => {
  const session = ctx.session.get();

  if (session?.step === "waiting_name") {
    // Update session state
    ctx.session.update({
      name: ctx.message?.text,
      step: "waiting_age"
    });
    await ctx.reply(`Hi ${ctx.message?.text}! How old are you?`);
  } else if (session?.step === "waiting_age") {
    await ctx.reply(`Registered! Name: ${session.name}, Age: ${ctx.message?.text}`);
    // Clear session
    ctx.session.delete();
  }
});

Session Methods:

| Method | Description | |--------|-------------| | ctx.session.get<T>() | Get session data | | ctx.session.set(value, ttl?) | Set session data (with optional TTL in seconds) | | ctx.session.update(partial) | Merge partial data into session | | ctx.session.delete() | Delete session for current user | | ctx.session.clear() | Alias for delete() |

Features:

  • Per-user and per-chat isolation
  • Optional TTL (auto-expiry in seconds)
  • Automatic cleanup of expired entries
  • In-memory storage (fast, no dependencies)

6. Middleware System

Compose reusable logic that runs before every update:

// Logging middleware
bot.use(async (ctx, next) => {
  console.log(`[${new Date().toISOString()}] ${ctx.from?.id}: ${ctx.message?.text}`);
  await next(); // Continue to next middleware
});

// Admin-only middleware
bot.use(async (ctx, next) => {
  if (ctx.message?.text?.startsWith("/admin")) {
    if (!isAdmin(ctx.from?.id)) {
      await ctx.reply("❌ Unauthorized");
      return; // Stop execution
    }
  }
  await next();
});

// Error middleware
bot.useError(async (error, ctx, next) => {
  console.error("Error:", error);
  await ctx.reply("Something went wrong!");
});

Middleware Features:

  • Runs in registration order
  • next() continues to the next middleware or final handler
  • return (without next) stops execution
  • Dedicated error middleware via useError()

Middleware Signature:

type MiddlewareFunction = (
  ctx: Context,
  next: () => Promise<void>
) => void | Promise<void>;

type ErrorMiddlewareFunction = (
  error: any,
  ctx: Context,
  next: () => Promise<void>
) => void | Promise<void>;

📖 API Reference

Message Methods

bot.sendMessage(chatId, text, options)

await bot.sendMessage(123456789, "Hello World!", {
  parse_mode: "HTML",
  disable_notification: false,
  reply_markup: {
    inline_keyboard: [[
      { text: "Click Me", callback_data: "click" }
    ]]
  }
});

bot.sendPhoto(chatId, photo, options)

await bot.sendPhoto(123456789, "https://example.com/photo.jpg", {
  caption: "My Photo",
  reply_markup: {
    inline_keyboard: [[
      { text: "Like", callback_data: "like" }
    ]]
  }
});

Other Message Methods

| Method | Description | |--------|-------------| | bot.sendDocument(chatId, doc, options) | Send a document | | bot.sendVideo(chatId, video, options) | Send a video | | bot.sendAudio(chatId, audio, options) | Send audio | | bot.sendVoice(chatId, voice, options) | Send voice message | | bot.sendSticker(chatId, sticker, options) | Send a sticker | | bot.sendLocation(chatId, lat, lon, options) | Send location | | bot.sendContact(chatId, phone, name, options) | Send contact | | bot.sendChatAction(chatId, action) | Send chat action | | bot.forwardMessage(chatId, fromChat, msgId) | Forward message | | bot.copyMessage(chatId, fromChat, msgId) | Copy message |


Edit Methods

bot.editMessageText(options)

await bot.editMessageText({
  chat_id: 123456789,
  message_id: 12345,
  text: "Updated text",
  reply_markup: {
    inline_keyboard: [[
      { text: "New Button", callback_data: "new" }
    ]]
  }
});

bot.editMessageReplyMarkup(chatId, messageId, replyMarkup)

await bot.editMessageReplyMarkup(
  123456789,
  12345,
  {
    inline_keyboard: [[
      { text: "Button 1", callback_data: "btn1" },
      { text: "Button 2", callback_data: "btn2" }
    ]]
  }
);

Other Edit Methods

| Method | Description | |--------|-------------| | bot.editMessageCaption(chatId, msgId, caption) | Edit caption | | bot.deleteMessage(chatId, msgId) | Delete message |


Chat Methods

| Method | Description | |--------|-------------| | bot.getChat(chatId) | Get chat info | | bot.getChatMember(chatId, userId) | Get member info | | bot.getChatAdministrators(chatId) | Get admins | | bot.getChatMemberCount(chatId) | Get member count | | bot.banChatMember(chatId, userId, untilDate?) | Ban user | | bot.unbanChatMember(chatId, userId) | Unban user | | bot.restrictChatMember(chatId, userId, perms) | Restrict user | | bot.promoteChatMember(chatId, userId, options) | Promote user | | bot.leaveChat(chatId) | Leave chat | | bot.pinChatMessage(chatId, msgId) | Pin message | | bot.unpinChatMessage(chatId, msgId?) | Unpin message |


Payment Methods

bot.sendStarsInvoice(options)

await bot.sendStarsInvoice({
  chat_id: 123456789,
  title: "Premium Access",
  description: "30 days premium subscription",
  payload: "premium_30days",
  currency: "XTR",
  prices: [
    { label: "Premium", amount: 100 }
  ]
});

bot.answerPreCheckoutQuery(queryId, ok, errorMessage)

await bot.answerPreCheckoutQuery(
  "query_id_here",
  true, // Accept payment
  ""    // Optional error message if rejected
);

Payment Handlers

// Pre-checkout validation
bot.onPreCheckoutQuery(async (query) => {
  const orderExists = await checkOrder(query.invoice_payload);
  return orderExists; // true = accept, false = reject
});

// Successful payment
bot.onSuccessfulPayment(async (payment) => {
  console.log("Payment received:", payment);
});

Keyboard Helpers

keyboard(buttons, options)

const replyKeyboard = keyboard([
  ["Button 1", "Button 2"],
  ["Button 3"]
], {
  resize_keyboard: true,     // Default: true
  one_time_keyboard: false,
  is_persistent: false,
  input_field_placeholder: "Select an option"
});

inlineKeyboard(buttons)

const inlineKeyboardMarkup = inlineKeyboard([
  [
    { text: "Button 1", callback_data: "btn1" },
    { text: "Open URL", url: "https://example.com" }
  ],
  [
    { text: "Open Mini App", web_app: { url: "https://app.example.com" } },
    { text: "Switch Query", switch_inline_query: "search term" }
  ]
]);

removeKeyboard(selective)

await bot.sendMessage(chatId, "Keyboard removed", {
  reply_markup: removeKeyboard()
});

forceReply(placeholder, selective)

await bot.sendMessage(chatId, "Please reply", {
  reply_markup: forceReply("Type your answer...")
});

Bot Methods

| Method | Description | |--------|-------------| | bot.getMe() | Get bot info | | bot.setMyCommands(commands) | Set command list | | bot.getMyCommands() | Get command list | | bot.deleteMyCommands() | Delete command list | | bot.logOut() | Log out from cloud | | bot.close() | Close bot instance | | bot.start() | Start polling | | bot.stop() | Stop polling and cleanup |


Webhook Methods

| Method | Description | |--------|-------------| | bot.setWebhook(options) | Set webhook URL | | bot.deleteWebhook(dropPending?) | Delete webhook | | bot.getWebhookInfo() | Get webhook info | | bot.processUpdate(update) | Process an update manually |


🔧 Advanced Usage

Rate Limiting

Protect your bot from abuse:

// Configure rate limiting
bot.useRateLimit({
  maxRequests: 10,    // Maximum requests
  windowMs: 1000,     // Time window (1 second)
  perUser: true,      // Limit per user
  perChat: false,     // Limit per chat
  global: false       // Global limit
});

Rate Limit Options:

| Option | Type | Default | Description | |--------|------|---------|-------------| | maxRequests | number | 30 | Max requests per window | | windowMs | number | 1000 | Window duration in ms | | perUser | boolean | true | Limit per user ID | | perChat | boolean | false | Limit per chat ID | | global | boolean | false | Global rate limit |


Request Queue

Control API request concurrency:

bot.queue({
  concurrency: 2,  // Max simultaneous requests
  maxSize: 100     // Max queue size
});

// High priority request
await bot.api("sendMessage", {
  chat_id: chatId,
  text: "Urgent message"
}, 10); // Priority 10 (higher = more priority)

Queue Options:

| Option | Type | Default | Description | |--------|------|---------|-------------| | concurrency | number | 1 | Max parallel requests | | maxSize | number | 100 | Max queue size (rejects when full) |


Mini App Authentication

Backend (Node.js):

// Verify Mini App data
app.post("/api/auth", (req, res) => {
  const initData = req.body.initData;

  // Validate and extract user
  const user = bot.verifyMiniAppInitData(initData);

  if (!user) {
    return res.status(401).json({ error: "Invalid authentication" });
  }

  // User is authenticated
  console.log(user.id, user.first_name);
  res.json({ user });
});

Frontend (Mini App):

// Get initData from Telegram
const initData = window.Telegram.WebApp.initData;

// Send to your backend
fetch("/api/auth", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ initData })
});

Webhook Setup

// Set webhook
await bot.setWebhook({
  url: "https://your-server.com/webhook",
  secret_token: "your-secret-token",
  max_connections: 40,
  allowed_updates: ["message", "callback_query"]
});

// Process updates from webhook
app.post("/webhook", async (req, res) => {
  const update = req.body;

  // Process update
  await bot.processUpdate(update);

  res.sendStatus(200);
});

Inline Queries

bot.on("inline_query", async (ctx) => {
  const query = ctx.update.inline_query;

  const results = [
    {
      type: "article",
      id: "1",
      title: "Result 1",
      input_message_content: {
        message_text: "You selected result 1"
      }
    }
  ];

  await bot.answerInlineQuery(query.id, results);
});

⚡ Performance Optimization

Memory Management

telegrams-node-bot automatically manages memory:

// Bounded queues prevent memory exhaustion
bot.queue({
  concurrency: 2,
  maxSize: 100  // Rejects when full
});

// Rate limiter auto-cleans expired entries
bot.useRateLimit({
  maxRequests: 10,
  windowMs: 1000
});

CPU Optimization

  • Map-based lookups: Commands resolved in O(1) time
  • No unnecessary parsing: Minimal JSON transformations
  • Efficient polling: Long polling with configurable timeout
  • Async processing: Non-blocking operations

Best Practices

// ✅ DO: Use specific handlers
bot.command("start", handleStart);

// ❌ DON'T: Loop through all messages
bot.on("message", async (ctx) => {
  if (ctx.message?.text === "/start") {
    // Slow - scans all messages
  }
});

// ✅ DO: Set appropriate limits
bot.queue({ concurrency: 2, maxSize: 50 });

// ❌ DON'T: Unlimited queue
bot.queue({ concurrency: 100, maxSize: 10000 });

🔒 Security Best Practices

1. Protect Your Token

// ✅ DO: Use environment variables
const bot = new LiteGram({
  token: process.env.BOT_TOKEN
});

// ❌ DON'T: Hardcode tokens
const bot = new LiteGram({
  token: "123456:ABC-DEF1234"
});

2. Validate Mini App Data

// ✅ DO: Always validate server-side
const user = bot.verifyMiniAppInitData(initData);

// ❌ DON'T: Trust client data
const user = JSON.parse(initDataUnsafe.user);

3. Validate Payments

// ✅ DO: Verify payment callbacks
bot.onPreCheckoutQuery(async (query) => {
  const orderExists = await checkOrder(query.invoice_payload);
  return orderExists;
});

// ❌ DON'T: Accept all payments blindly
bot.onPreCheckoutQuery(async () => true);

4. Use Rate Limiting

// ✅ DO: Protect against spam
bot.useRateLimit({
  maxRequests: 5,
  windowMs: 1000,
  perUser: true
});

5. Validate User Input

bot.command("set_name", async (ctx) => {
  const name = ctx.message?.text?.replace("/set_name ", "").trim();

  // ✅ DO: Validate input
  if (!name || name.length > 50) {
    return ctx.reply("Invalid name");
  }

  // Save validated input
  ctx.session.set({ name });
  await ctx.reply("Name saved!");
});

📝 TypeScript Support

telegrams-node-bot is written in TypeScript and provides full type definitions:

import {
  LiteGram,
  Context,
  TelegramMessage,
  TelegramUser,
  CallbackQuery,
  SendMessageOptions,
  InlineKeyboardMarkup
} from "telegrams-node-bot";

// Strongly typed handlers
const handleStart = async (ctx: Context): Promise<void> => {
  const user: TelegramUser | undefined = ctx.from;
  const message: TelegramMessage | undefined = ctx.message;

  const options: SendMessageOptions = {
    parse_mode: "HTML",
    reply_markup: {
      inline_keyboard: [[
        { text: "Button", callback_data: "btn" }
      ]]
    }
  };

  await ctx.reply("Hello!", options);
};

bot.command("start", handleStart);

💡 Examples

Complete Payment Bot

import { LiteGram, keyboard, inlineKeyboard } from "telegrams-node-bot";

const bot = new LiteGram({
  token: process.env.BOT_TOKEN,
  polling: true
});

// Product catalog
const products = {
  basic: { title: "Basic Plan", price: 50, emoji: "⭐" },
  pro: { title: "Pro Plan", price: 100, emoji: "🌟" },
  vip: { title: "VIP Plan", price: 500, emoji: "💎" }
};

// Show products
bot.command("products", async (ctx) => {
  const buttons = Object.entries(products).map(([key, product]) => [{
    text: `${product.emoji} ${product.title} - ${product.price} ⭐`,
    callback_data: `buy_${key}`
  }]);

  await ctx.reply("Choose a product:", {
    reply_markup: inlineKeyboard(buttons)
  });
});

// Handle purchase
bot.on("callback_query", async (ctx) => {
  const data = ctx.callbackQuery?.data;

  if (data?.startsWith("buy_")) {
    const productKey = data.replace("buy_", "");
    const product = products[productKey];

    await ctx.sendStarsInvoice({
      title: product.title,
      description: `${product.title} subscription`,
      payload: `purchase_${productKey}`,
      currency: "XTR",
      prices: [{ label: product.title, amount: product.price }]
    });
  }
});

// Handle payments
bot.onPreCheckoutQuery(async (query) => true);

bot.onSuccessfulPayment(async (payment) => {
  console.log("Payment received:", payment);
});

bot.start();

Multi-Step Registration with Session

import { LiteGram } from "telegrams-node-bot";

const bot = new LiteGram({
  token: process.env.BOT_TOKEN,
  polling: true
});

bot.command("register", async (ctx) => {
  ctx.session.set({ step: "name" });
  await ctx.reply("📝 What's your name?");
});

bot.on("message", async (ctx) => {
  const session = ctx.session.get();

  if (session?.step === "name") {
    ctx.session.update({ name: ctx.message?.text, step: "age" });
    await ctx.reply("🎂 How old are you?");
  } else if (session?.step === "age") {
    ctx.session.update({ age: ctx.message?.text, step: "email" });
    await ctx.reply("📧 What's your email?");
  } else if (session?.step === "email") {
    const data = {
      name: session.name,
      age: session.age,
      email: ctx.message?.text
    };

    await ctx.reply(
      `✅ Registration complete!\n\n` +
      `Name: ${data.name}\n` +
      `Age: ${data.age}\n` +
      `Email: ${data.email}`
    );

    ctx.session.delete();
  }
});

bot.start();

Middleware Example

import { LiteGram } from "telegrams-node-bot";

const bot = new LiteGram({
  token: process.env.BOT_TOKEN,
  polling: true
});

const ADMIN_IDS = [123456, 789012];

// Logging middleware
bot.use(async (ctx, next) => {
  const start = Date.now();
  console.log(`📩 ${ctx.from?.id}: ${ctx.message?.text || "callback"}`);
  await next();
  console.log(`⏱️ ${Date.now() - start}ms`);
});

// Admin-only middleware
bot.use(async (ctx, next) => {
  if (ctx.message?.text?.startsWith("/admin")) {
    if (!ctx.from || !ADMIN_IDS.includes(ctx.from.id)) {
      return ctx.reply("❌ Unauthorized");
    }
  }
  await next();
});

// Error middleware
bot.useError(async (error, ctx) => {
  console.error("Error:", error);
  await ctx.reply("⚠️ Something went wrong. Please try again.");
});

bot.command("admin", async (ctx) => {
  await ctx.reply("👑 Welcome, admin!");
});

bot.start();

Mini App Authentication Server

import { LiteGram } from "telegrams-node-bot";
import http from "http";

const bot = new LiteGram({
  token: process.env.BOT_TOKEN
});

const server = http.createServer((req, res) => {
  if (req.url === "/auth" && req.method === "POST") {
    let body = "";

    req.on("data", chunk => body += chunk);

    req.on("end", () => {
      const { initData } = JSON.parse(body);
      const user = bot.verifyMiniAppInitData(initData);

      if (!user) {
        res.writeHead(401);
        res.end(JSON.stringify({ error: "Unauthorized" }));
        return;
      }

      res.writeHead(200, { "Content-Type": "application/json" });
      res.end(JSON.stringify({ user }));
    });
  }
});

server.listen(3000);

🤝 Contributing

We welcome contributions! Please follow these steps:

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Run tests: npm test
  5. Build: npm run build
  6. Submit a pull request

📄 License

MIT License — see LICENSE file for details.


🔗 Links


💬 Support


Made with ❤️ for the Telegram community

Remember: telegrams-node-bot is designed to be simple, fast, and efficient. Keep it lightweight!