Skip to content

b-codex/telegram-bot-sdk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

telegram-bot-kit

telegram-bot-kit is a lightweight, TypeScript-first SDK for building Telegram bots in Node.js and Next.js. Designed for serverless deployments (e.g., Vercel), it provides a simple, event-driven wrapper around the Telegram Bot API, enabling full control over messaging, media, interactions, and more.

Features

Core Messaging

  • Send text messages with formatting, keyboards, and markup
  • Edit, delete, and replace messages
  • Handle callback queries and answer buttons

Media Support

  • Send photos, audio, voice, animations, stickers, polls, venues, and contacts
  • Upload files via URLs or local buffers/streams
  • Download user-uploaded files

Interactive Elements

  • Inline keyboards and reply keyboards
  • Force reply and one-time keyboards
  • Polls and venue sharing

Chat Management

  • Forward messages
  • Pin/unpin messages (single or all)
  • Delete messages

Advanced Handling

  • Full event-driven update processing (messages, callbacks, polls, payments, etc.)
  • Inline query and chosen inline result support
  • Error handling with descriptive API exceptions
  • TypeScript interfaces for all Telegram structures

Deployment Ready

  • Webhook-first design (no polling needed)
  • ESM compatible (Node.js >=18)
  • Lightweight with zero external runtime dependencies (uses only cross-fetch for HTTP)

Installation

npm install telegram-bot-kit

Quick Start

  1. Create a Bot: Talk to @BotFather and get your token.

  2. Basic Usage:

import { TelegramBot } from 'telegram-bot-kit';

const bot = new TelegramBot('YOUR_BOT_TOKEN');
  1. Handle Messages (Webhook Example):
import { createWebhookHandler } from 'telegram-bot-kit';

// In your server (e.g., Next.js API route)
const handler = createWebhookHandler(bot, 'YOUR_WEBHOOK_SECRET');

bot.on('message', (msg) => {
  if (msg.text === '/start') {
    bot.sendMessage(msg.chat.id, 'Hello! Welcome to telegram-bot-kit.');
  }
});
  1. Deploy: Set your webhook and deploy to Vercel!

Usage Examples

Sending Messages with Options

// Simple text
await bot.sendMessage(chatId, 'Hello World!');

// With inline keyboard
const keyboard = {
  inline_keyboard: [
    [{ text: 'Yes', callback_data: 'yes' }, { text: 'No', callback_data: 'no' }]
  ]
};
await bot.sendMessage(chatId, 'Choose:', { reply_markup: keyboard });

// With reply keyboard
const replyMarkup = {
  keyboard: [[{ text: 'Button 1' }, { text: 'Button 2' }]],
  one_time_keyboard: true
};
await bot.sendMessage(chatId, 'Choose an option:', { reply_markup: replyMarkup });

Media Sending

// Send photo from URL
await bot.sendPhoto(chatId, 'https://example.com/photo.jpg', 'Caption here');

// Upload audio file
const audioBuffer = fs.readFileSync('audio.mp3');
await bot.sendAudio(chatId, audioBuffer, 'Audio title', { duration: 120 });

// Send poll
await bot.sendPoll(chatId, 'What\'s your favorite?', ['Option 1', 'Option 2'], {
  is_anonymous: false, allows_multiple_answers: true
});

Handling Interactions

// Handle callbacks (button presses)
bot.on('callback_query', (query) => {
  bot.answerCallbackQuery(query.id, 'Button clicked!');
  bot.sendMessage(query.message.chat.id, `You chose: ${query.data}`);
});

// Handle location requests
bot.on('message', (msg) => {
  if (msg.location) {
    const { latitude, longitude } = msg.location;
    bot.sendVenue(msg.chat.id, latitude, longitude, 'Your Location', 'Address here');
  }
});

// Inline queries (when users @mention your bot)
bot.on('inline_query', (query) => {
  // Respond to user searches
  bot.answerInlineQuery(query.id, [{
    type: 'article',
    id: '1',
    title: 'Sample Result',
    input_message_content: { message_text: 'Inline result!' }
  }]);
});

Editing and Deleting

// Send initial message
const msg = await bot.sendMessage(chatId, 'Initial text');
const messageId = msg.result.message_id;

// Edit text
await bot.editMessageText(chatId, messageId, 'Updated text', { parse_mode: 'Markdown' });

// Delete after delay
setTimeout(() => bot.deleteMessage(chatId, messageId), 5000);

File Downloads

// Get file info
const fileResponse = await bot.getFile('file_id_from_message');
const fileObj = fileResponse.result;

// Get download URL
const downloadUrl = bot.getFileDownloadUrl(fileObj);

// Download using fetch
const response = await fetch(downloadUrl);
const buffer = await response.arrayBuffer();
// Save or process buffer

Webhook Setup (Next.js)

In api/telegram-webhook.ts:

import { TelegramBot, createWebhookHandler } from 'telegram-bot-kit';

const bot = new TelegramBot();
const handler = createWebhookHandler(bot, process.env.WEBHOOK_SECRET);

export default handler;

Set webhook in your bot setup:

import { setWebhook } from 'telegram-bot-kit';

await setWebhook(token, { url: 'https://your-domain.com/api/telegram-webhook' });

API Reference

TelegramBot Methods

Core Messaging

sendMessage(chatId, text, options?)

Send a text message with optional formatting, keyboards, etc.

// Simple message
await bot.sendMessage(chatId, 'Hello World!');

// With Markdown formatting
await bot.sendMessage(chatId, 'Hello **world**!', { parse_mode: 'Markdown' });

// With inline keyboard
await bot.sendMessage(chatId, 'Choose an option:', {
  reply_markup: {
    inline_keyboard: [
      [{ text: 'Yes', callback_data: 'yes_action' }, { text: 'No', callback_data: 'no_action' }]
    ]
  }
});

// With reply keyboard
await bot.sendMessage(chatId, 'Select:', {
  reply_markup: {
    keyboard: [[{ text: 'Option 1' }, { text: 'Option 2' }]],
    one_time_keyboard: true
  }
});

// Disable notifications
await bot.sendMessage(chatId, 'Silent message', { disable_notification: true });
editMessageText(chatId, messageId, text, options?)

Edit an existing text message.

const msg = await bot.sendMessage(chatId, 'Initial text');
const messageId = msg.result.message_id;

await bot.editMessageText(chatId, messageId, 'Updated text', { parse_mode: 'HTML' });
editMessageCaption(chatId, messageId, caption?, options?)

Edit a message's caption.

await bot.editMessageCaption(chatId, messageId, 'New caption', { parse_mode: 'Markdown' });
deleteMessage(chatId, messageId)

Delete a message.

await bot.deleteMessage(chatId, messageId);

Keyboard & Interactions

answerCallbackQuery(callbackQueryId, options?)

Answer a callback query from an inline keyboard.

bot.on('callback_query', async (query) => {
  await bot.answerCallbackQuery(query.id, {
    text: 'Processing your choice...',
    show_alert: false
  });
});
editMessageReplyMarkup(chatId, messageId, replyMarkup)

Edit a message's inline keyboard markup.

await bot.editMessageReplyMarkup(chatId, messageId, {
  inline_keyboard: [[{ text: 'New Button', callback_data: 'new_action' }]]
});
sendInlineButtons(chatId, text, rows, opts?)

Send a message with inline keyboard (convenience method).

await bot.sendInlineButtons(chatId, 'Choose action:', [
  [{ text: 'Yes', callback_data: 'yes' }, { text: 'No', callback_data: 'no' }],
  [{ text: 'Maybe', callback_data: 'maybe' }]
]);
sendButtons(chatId, text, rows, resizeKeyboard?, oneTimeKeyboard?)

Send a message with reply keyboard (convenience method).

await bot.sendButtons(chatId, 'Choose an option:', [
  [{ text: 'Option 1' }, { text: 'Option 2' }],
  [{ text: 'Cancel' }]
], true, false); // resize_keyboard: true, one_time_keyboard: false
requestPhoneNumber(chatId, prompt?)

Request user's phone number with a reply keyboard.

await bot.requestPhoneNumber(chatId, 'Please share your contact to continue.');
bot.on('contact', (contact) => {
  console.log('Phone:', contact.contact?.phone_number);
});
requestLocation(chatId, prompt?)

Request user's location with a reply keyboard.

await bot.requestLocation(chatId, 'Where are you?');
bot.on('location', (location) => {
  console.log('Coords:', location.location?.latitude, location.location?.longitude);
});
hideKeyboard(chatId, text?)

Hide/remove the custom keyboard for a user.

await bot.hideKeyboard(chatId, 'Keyboard hidden!');

Media

sendPhoto(chatId, photo, caption?, options?)

Send a photo (URL, Buffer, or file path).

// From URL
await bot.sendPhoto(chatId, 'https://example.com/photo.jpg', 'Photo caption');

// From file (Node.js)
const photoBuffer = require('fs').readFileSync('photo.jpg');
await bot.sendPhoto(chatId, photoBuffer, 'Uploaded photo', { filename: 'my_photo.jpg' });
sendAudio(chatId, audio, caption?, options?)

Send an audio file.

const audioBuffer = require('fs').readFileSync('song.mp3');
await bot.sendAudio(chatId, audioBuffer, 'Song title', {
  duration: 180,
  title: 'Track Name',
  performer: 'Artist'
});
sendVoice(chatId, voice, caption?, options?)

Send a voice message.

const voiceBuffer = require('fs').readFileSync('voice.ogg');
await bot.sendVoice(chatId, voiceBuffer, 'Voice note');
sendAnimation(chatId, animation, caption?, options?)

Send an animation/GIF.

await bot.sendAnimation(chatId, 'https://example.com/animation.gif', 'Cute animation!');
sendSticker(chatId, sticker, options?)

Send a sticker.

const stickerBuffer = require('fs').readFileSync('sticker.webp');
await bot.sendSticker(chatId, stickerBuffer);
sendDocument(chatId, document, caption?, options?)

Send a document/file.

const fileBuffer = require('fs').readFileSync('document.pdf');
await bot.sendDocument(chatId, fileBuffer, 'Important document', {
  filename: 'report.pdf'
});
sendVideo(chatId, video, caption?, options?)

Send a video file.

const videoBuffer = require('fs').readFileSync('video.mp4');
await bot.sendVideo(chatId, videoBuffer, 'Video description');
sendPoll(chatId, question, options, opts?)

Send a poll.

await bot.sendPoll(chatId, 'What\'s your favorite color?', ['Red', 'Blue', 'Green'], {
  is_anonymous: false,
  allows_multiple_answers: true,
  correct_option_id: 1, // For quiz mode
  explanation: 'Blue is the most popular!'
});
sendVenue(chatId, latitude, longitude, title, address, opts?)

Send a venue/location.

await bot.sendVenue(chatId, 40.7128, -74.0060, 'New York City', 'Manhattan, NY');
sendContact(chatId, phoneNumber, firstName, opts?)

Send a contact.

await bot.sendContact(chatId, '+1234567890', 'John Doe', {
  last_name: 'Smith',
  vcard: 'BEGIN:VCARD\\nVERSION:3.0\\nFN:John Doe\\nTEL:+1234567890\\nEND:VCARD'
});

Chat Management

forwardMessage(chatId, fromChatId, messageId, opts?)

Forward a message from one chat to another.

await bot.forwardMessage(myChatId, originalChatId, messageId, {
  disable_notification: true
});
pinChatMessage(chatId, messageId, opts?)

Pin a message in a chat.

await bot.pinChatMessage(chatId, messageId, {
  disable_notification: false
});
unpinChatMessage(chatId, messageId)

Unpin a specific message.

await bot.unpinChatMessage(chatId, messageId);
unpinAllChatMessages(chatId)

Unpin all pinned messages in a chat.

await bot.unpinAllChatMessages(chatId);

Files

getFile(fileId)

Get file information and download path.

const fileResponse = await bot.getFile('file_id_from_message');
console.log('Download URL available at:', bot.getFileDownloadUrl(fileResponse.result));
getFileDownloadUrl(file)

Generate a download URL for a file object.

const file = { file_path: 'path/to/file' };
const url = bot.getFileDownloadUrl(file);
// Use with fetch or display/download

Convenience Methods

replaceMessage(chatId, messageId, text, opts?)

Alias for editMessageText (shorter name).

await bot.replaceMessage(chatId, messageId, 'New content');

Update Handling

handleUpdate(update)

Process a Telegram update and emit appropriate events.

// In webhook handler
export async function POST(req) {
  const update = await req.json();
  bot.handleUpdate(update);
  return new Response('OK');
}

Utility Functions (Outside TelegramBot Class)

setWebhook(token, options)

Set or delete a webhook for your bot.

import { setWebhook } from 'telegram-bot-kit';

await setWebhook('your_bot_token', {
  url: 'https://yourapp.com/webhook',
  secret_token: 'secret_for_webhooks',
  max_connections: 100,
  allowed_updates: ['message', 'callback_query']
});

// To remove webhook (delete)
await setWebhook('your_bot_token', { url: '' });

createWebhookHandler(bot, secret?)

Create a request handler for processing Telegram webhooks.

import { createWebhookHandler } from 'telegram-bot-kit';

const webhookHandler = createWebhookHandler(bot, 'your_secret_token');

// Express.js example
app.post('/telegram-webhook', webhookHandler);

// Next.js API route
export default webhookHandler;

Update Handling

handleUpdate(update)

Process a Telegram update and emit appropriate events.

// In webhook handler
export async function POST(req) {
  const update = await req.json();
  bot.handleUpdate(update);
  return new Response('OK');
}

Utility Functions (Outside TelegramBot Class)

setWebhook(token, options)

Set or delete a webhook for your bot.

import { setWebhook } from 'telegram-bot-kit';

await setWebhook('your_bot_token', {
  url: 'https://yourapp.com/webhook',
  secret_token: 'secret_for_webhooks',
  max_connections: 100,
  allowed_updates: ['message', 'callback_query']
});

// To remove webhook (delete)
await setWebhook('your_bot_token', { url: '' });

createWebhookHandler(bot, secret?)

Create a request handler for processing Telegram webhooks.

import { createWebhookHandler } from 'telegram-bot-kit';

const webhookHandler = createWebhookHandler(bot, 'your_secret_token');

// Express.js example
app.post('/telegram-webhook', webhookHandler);

// Next.js API route
export default webhookHandler;

Events

All events receive the corresponding Telegram object as the first parameter.

Message Events

(Triggered by user actions like sending messages; use with sendMessage method)

message - User sent a message, photo, document, etc.
bot.on('message', (msg) => {
  if (msg.text === '/start') {
    bot.sendMessage(msg.chat.id, 'Welcome!');
  }
});
edited_message - User edited a message
bot.on('edited_message', (msg) => {
  bot.sendMessage(msg.chat.id, 'Message edited!');
});
channel_post - New post in channel
bot.on('channel_post', (msg) => {
  console.log('New channel post:', msg.text);
});
edited_channel_post - Edited channel post
bot.on('edited_channel_post', (msg) => {
  console.log('Channel post edited:', msg.text);
});

Interaction Events

callback_query - User pressed an inline keyboard button
bot.on('callback_query', async (query) => {
  await bot.answerCallbackQuery(query.id, 'Button clicked!');
  await bot.sendMessage(query.message.chat.id, `You chose: ${query.data}`);
});
inline_query - User typed @bot and is searching
bot.on('inline_query', async (query) => {
  const results = [
    { type: 'article', id: '1', title: 'Result 1', input_message_content: { message_text: 'Content 1' } }
  ];
  await bot.answerInlineQuery(query.id, results);
});
chosen_inline_result - User selected an inline result
bot.on('chosen_inline_result', (result) => {
  console.log('User chose:', result.result_id);
});

Location/Contact Events

contact - User shared contact
bot.on('contact', (contact) => {
  console.log('Phone:', contact.contact?.phone_number, 'Name:', contact.contact?.first_name);
});
location - User shared location
bot.on('location', (location) => {
  const { latitude, longitude } = location.location!;
  bot.sendMessage(location.chat.id, `Your coords: ${latitude}, ${longitude}`);
});

Payment Events (for payment bots)

shipping_query - User selected shipping option
bot.on('shipping_query', async (query) => {
  // Answer with shipping options
});
pre_checkout_query - User is about to pay
bot.on('pre_checkout_query', async (query) => {
  // Validate payment (ok: true/false)
});

Poll Events

poll - Poll was updated
bot.on('poll', (poll) => {
  console.log('Poll updated:', poll.question, 'Total votes:', poll.total_voter_count);
});
poll_answer - User voted in poll
bot.on('poll_answer', (answer) => {
  console.log('User voted options:', answer.option_ids);
});

Admin Events

my_chat_member - Bot's membership status changed
bot.on('my_chat_member', (update) => {
  console.log('Bot membership changed:', update.new_chat_member.status);
});
chat_member - Another member's status changed
bot.on('chat_member', (update) => {
  console.log(update.new_chat_member.user.first_name, 'is now', update.new_chat_member.status);
});
chat_join_request - User requested to join private group/channel
bot.on('chat_join_request', (request) => {
  // Approve or decline join request
  console.log(request.from.first_name, 'wants to join', request.chat.title);
});

Options Object

Most methods accept an options object for parameters like:

  • parse_mode: 'Markdown' | 'HTML' | 'MarkdownV2'
  • disable_notification: boolean
  • reply_markup: Inline or reply keyboard
  • And more per Telegram API docs.

TypeScript Support

Full type safety with interfaces for:

  • Message, User, Chat, Update, CallbackQuery, etc.
  • Import from telegram-bot-kit for direct use.

Error Handling

Methods throw Error with Telegram's API description on failure. Wrap calls in try-catch:

try {
  await bot.sendMessage(chatId, 'Test');
} catch (error) {
  console.error('API Error:', error.message);
}

Environment Variables

  • TELEGRAM_BOT_TOKEN: Bot token (can also pass directly to constructor)

Change Log

v1.0.3

  • Fixed Next.js build failures by replacing node-fetch with cross-fetch for isomorphic HTTP support, enabling client-side bundling compatibility.

License

  • TELEGRAM_BOT_TOKEN: Bot token (can also pass directly to constructor)

License

MIT

Contributing

Fork and submit PRs. For major changes, open an issue first.

Built for simplicity, power, and serverless compatibility!

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published