Skills telegram-bot-builder

install
source · Clone the upstream repo
git clone https://github.com/TerminalSkills/skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/TerminalSkills/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/telegram-bot-builder" ~/.claude/skills/terminalskills-skills-telegram-bot-builder && rm -rf "$T"
manifest: skills/telegram-bot-builder/SKILL.md
safety · automated scan (medium risk)
This is a pattern-based risk scan, not a security review. Our crawler flagged:
  • pip install
  • references .env files
Always read a skill's source content before installing. Patterns alone don't mean the skill is malicious — but they warrant attention.
source content

Telegram Bot Builder

Overview

Builds production-ready Telegram bots covering the full Bot API surface: commands, inline keyboards, callback queries, conversations with state machines, media handling, group management, payments, and Mini Apps. Supports both long polling (development) and webhooks (production).

Instructions

1. Bot Creation

  1. Message @BotFather on Telegram
  2. Send
    /newbot
    , choose name and username
  3. Save the bot token (format:
    123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11
    )
  4. Configure with
    /setcommands
    ,
    /setdescription
    ,
    /setabouttext

2. Project Scaffolding

Recommended frameworks by language:

Node.js — grammY (recommended):

npm init -y && npm install grammy dotenv

Node.js — Telegraf:

npm install telegraf dotenv

Python — python-telegram-bot:

pip install python-telegram-bot python-dotenv

Standard project structure:

telegram-bot/
├── bot.js                # Entry point, bot initialization
├── handlers/
│   ├── commands.js       # /start, /help, custom commands
│   ├── callbacks.js      # Inline keyboard callback handlers
│   ├── conversations.js  # Multi-step conversation flows
│   └── middleware.js      # Auth, logging, rate limiting
├── keyboards/            # Inline and reply keyboard builders
├── services/             # Business logic
├── .env                  # BOT_TOKEN, WEBHOOK_URL, ADMIN_ID
└── package.json

3. Core Patterns (grammY)

Basic command handler:

bot.command('start', async (ctx) => {
  await ctx.reply('Welcome!', {
    reply_markup: {
      inline_keyboard: [[
        { text: '📊 Dashboard', callback_data: 'dashboard' },
        { text: '⚙️ Settings', callback_data: 'settings' }
      ]]
    }
  });
});

Callback query handler:

bot.callbackQuery('dashboard', async (ctx) => {
  await ctx.answerCallbackQuery();
  await ctx.editMessageText('Here is your dashboard...', {
    reply_markup: backButton
  });
});

Conversation with sessions:

bot.use(session({ initial: () => ({ step: 'idle' }) }));
bot.use(conversations());
bot.use(createConversation('onboarding', onboardingFlow));

async function onboardingFlow(conversation, ctx) {
  await ctx.reply('What is your name?');
  const name = await conversation.wait();
  await ctx.reply('What is your email?');
  const email = await conversation.wait();
  await ctx.reply(`Thanks ${name.message.text}! Registered with ${email.message.text}`);
}

Middleware for auth:

function adminOnly(ctx, next) {
  if (ctx.from?.id !== Number(process.env.ADMIN_ID)) {
    return ctx.reply('⛔ Not authorized');
  }
  return next();
}
bot.command('admin', adminOnly, handleAdmin);

4. Keyboard Types

Inline Keyboard (attached to message):

  • Callback buttons (
    callback_data
    ) — triggers callbackQuery handler
  • URL buttons (
    url
    ) — opens a link
  • Web App buttons (
    web_app
    ) — opens a Mini App
  • Switch Inline buttons (
    switch_inline_query
    ) — triggers inline mode

Reply Keyboard (replaces phone keyboard):

  • Custom keyboard with predefined responses
  • one_time_keyboard: true
    to auto-hide after selection
  • resize_keyboard: true
    for compact display

Remove Keyboard:

{ reply_markup: { remove_keyboard: true } }

5. Polling vs Webhooks

Long Polling (development):

bot.start(); // Calls getUpdates in a loop
  • No public URL needed
  • Slightly higher latency
  • Good for development and low-traffic bots

Webhooks (production):

// With express
const app = express();
app.use(express.json());
app.use(`/bot${token}`, webhookCallback(bot, 'express'));
app.listen(3000);

// Set webhook
await bot.api.setWebhook(`https://yourdomain.com/bot${token}`);
  • Requires HTTPS public URL
  • Lower latency, better for high traffic
  • Self-signed certificates supported with
    certificate
    parameter

6. Media Handling

// Send photo
await ctx.replyWithPhoto(new InputFile('./image.png'), { caption: 'Check this out' });

// Send document
await ctx.replyWithDocument(new InputFile(buffer, 'report.pdf'));

// Handle received photos
bot.on('message:photo', async (ctx) => {
  const file = await ctx.getFile();
  const url = `https://api.telegram.org/file/bot${token}/${file.file_path}`;
});

7. Bot API Limits

  • Messages: 30 messages/sec globally, 1 message/sec per chat in groups
  • Inline results: 50 results per query
  • File upload: 50 MB max (20 MB for photos)
  • File download: 20 MB via getFile
  • Message length: 4096 characters
  • Caption length: 1024 characters
  • Inline keyboard: 100 buttons per message
  • Webhook: 40M updates/hour

8. Deployment

  • Simple: Railway, Render, Fly.io (webhook mode)
  • Serverless: Vercel/AWS Lambda with webhook adapter
  • VPS: systemd service with auto-restart
  • Docker: Lightweight Node.js container with health checks

Examples

Example 1: Task Management Bot

Input: "Build a Telegram bot for my team to manage tasks. Users should be able to create tasks, assign them, set deadlines, and get reminders."

Output: A grammY bot with:

  • /newtask
    command opening a conversation flow (title → description → assignee → deadline)
  • Inline keyboard for task status updates (To Do → In Progress → Done)
  • Daily reminder messages for overdue tasks using node-cron
  • /mytasks
    showing personal task list with inline navigation
  • SQLite database for persistence via better-sqlite3

Example 2: Content Publishing Bot

Input: "Create a Telegram bot that lets me draft posts, preview them, schedule them to a channel, and track engagement."

Output: A grammY bot with:

  • Multi-step drafting flow with text, photos, and formatting preview
  • Schedule picker with inline calendar keyboard
  • Auto-publishing to target channel via
    bot.api.sendMessage(channelId, ...)
  • Engagement tracking by checking message views via
    getChat
    and forwarded counts
  • /drafts
    command listing scheduled posts with edit/delete options

Guidelines

  • Always handle errors in callbacks — unhandled errors kill the bot process
  • Use
    ctx.answerCallbackQuery()
    to dismiss the loading indicator on buttons
  • Store bot token in env vars, never hardcode
  • Use
    parse_mode: 'HTML'
    or
    'MarkdownV2'
    for rich text (MarkdownV2 requires escaping special chars)
  • Implement graceful shutdown:
    bot.stop()
    on SIGINT/SIGTERM
  • For groups: handle
    my_chat_member
    updates to track when bot is added/removed
  • Set commands list via
    bot.api.setMyCommands()
    for autocomplete
  • Use
    ctx.chatAction = 'typing'
    for long operations
  • Rate limit user interactions to prevent abuse
  • For conversations: always handle the case where the user sends an unexpected message type