🤖 RunMyBot – Telegraf Command Samples

Copy‑paste friendly snippets. Each block shows the command name, example code, and usage notes.

Tip: Replace placeholders like <TOKEN>, IDs, and URLs as needed.

🧱 Platform‑Safe Snippets for RunMyBot command box

These work inside your Commands editor without access to your backend, tokens, or imports. They use only the provided ctx (and Markup if exposed by the platform). Prefer URL buttons over callback buttons since per‑command code can’t register global handlers.

A1. /start – Welcome

Simple greet; no token or imports
// Command: /start
ctx.reply('👋 Welcome to RunMyBot! Use /help to see what I can do.');

A2. /help – Inline list

Keep short and actionable
// Command: /help
ctx.replyWithMarkdown('*Try:*
/info – your profile
/photo – random image
/poll – quick poll
/dice – roll a dice');

A3. /menu – URL Buttons (no callbacks)

Safe for single‑command execution
// Command: /menu
ctx.reply('Choose an option:', Markup.inlineKeyboard([
  [Markup.button.url('🌐 Website','https://runmybot.example')],
  [Markup.button.url('📚 Docs','https://runmybot.example/docs')],
  [Markup.button.url('🆘 Support','https://t.me/your_support_channel')]
]));

A4. /info – User info

Uses ctx.from only
// Command: /info
const u = ctx.from;
ctx.replyWithMarkdown(`*User*
ID: ${u.id}
Name: ${u.first_name} ${u.last_name||''}
Username: @${u.username||'none'}`);

A5. /echo – Echo back

No global state needed
// Command: /echo your text here
const txt = (ctx.message.text||'').split(' ').slice(1).join(' ');
ctx.reply(txt || 'Nothing to echo.');

A6. /photo – Remote image

Works with any public URL
// Command: /photo
ctx.replyWithPhoto({ url:'https://picsum.photos/640/360' }, { caption:'Random 📸' });

A7. /poll – Quick poll

No extra setup
// Command: /poll
ctx.replyWithPoll('Favorite stack?', ['MERN','MEAN','Django','Laravel'], { is_anonymous:false });

A8. /dice – Fun

Single call
// Command: /dice
ctx.replyWithDice();

A9. /contact – Share contact card

One‑shot API call
// Command: /contact
ctx.replyWithContact('+911234567890','Support','RunMyBot');

A10. /whoami – Debug update

Great for support
// Command: /whoami
ctx.reply('```
' + JSON.stringify(ctx.update, null, 2) + '
```', { parse_mode:'MarkdownV2' });
Why no callbacks/scenes here? In RunMyBot, each command runs in isolation, so global handlers like bot.action() or multi‑step wizards aren’t registered. Use URL buttons, force‑reply prompts, or separate commands instead.

⚙️ Quick Boilerplate start here

0. Minimal Bot Setup

Use to start a Telegraf bot quickly. Add handlers below.
// file: index.js
// npm i telegraf
const { Telegraf, Markup } = require('telegraf');
const bot = new Telegraf(process.env.BOT_TOKEN || '');

bot.start((ctx) => ctx.reply('👋 Welcome! Use /help to see commands.'));
bot.help((ctx) => ctx.reply('Try /menu, /photo, /dice, /poll, /echo ...'));

// Health ping (optional)
bot.command('ping', (ctx) => ctx.reply('pong'));

bot.launch();

// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));
Usage: node index.js after setting BOT_TOKEN. On Render/Vercel with webhook, use the webhook example below.

🧩 Basics

1. /start – Basic Greeting

Welcome message for new users
// Command: /start
ctx.reply('Hello 👋, welcome to RunMyBot!');

2. /help – Short Help

Explain available commands
// Command: /help
ctx.replyWithMarkdown('*Commands:*\n/start – greet\n/info – user info\n/echo – echo back\n/menu – inline menu');

3. /info – User Info

Reads ctx.from
// Command: /info
const u = ctx.from;
ctx.replyWithMarkdown(`*User Info*\n- ID: ${u.id}\n- Name: ${u.first_name} ${u.last_name||''}\n- Username: @${u.username||'none'}`);

4. /echo – Echo Text

Echoes whatever comes after command
// Command: /echo
// Usage: /echo your message
const text = ctx.message.text.split(' ').slice(1).join(' ');
ctx.reply(text || 'Nothing to echo.');

💬 Messaging & Formatting

5. /md – Markdown

Bold/italic/code formatting
// Command: /md
ctx.replyWithMarkdown('*Bold* _Italic_ `Code`\n[Link](https://t.me)');

6. /html – HTML

Send HTML formatted text
// Command: /html
ctx.replyWithHTML('Bold Italic Code');

7. /typing – Chat Action

Show typing/upload action
// Command: /typing
await ctx.sendChatAction('typing');
setTimeout(() => ctx.reply('Done typing…'), 1200);

8. /delete – Delete Message

Deletes the command message (bot must be admin in groups)
// Command: /delete
try { await ctx.deleteMessage(); } catch (e) { ctx.reply('I cannot delete this.'); }

🖼️ Media

9. /photo – Send Photo

Remote image URL + caption
// Command: /photo
ctx.replyWithPhoto({ url: 'https://picsum.photos/640/360' }, { caption: 'Random image' });

10. /video – Send Video

Remote video URL
// Command: /video
ctx.replyWithVideo({ url: 'https://file-examples.com/storage/fe1.mp4' });

11. /audio – Send Audio

Music/voice
// Command: /audio
ctx.replyWithAudio({ url:'https://file-examples.com/storage/fe1.mp3' }, { title:'Sample' });

12. /doc – Send Document

PDF or any file
// Command: /doc
ctx.replyWithDocument({ url:'https://file-examples.com/storage/fe1.pdf' });

13. /sticker – Send Sticker

By file_id or URL (webp/webm)
// Command: /sticker
ctx.replyWithSticker('CAACAgUAAxkBAAIBQ2T…'); // replace with a real file_id

🧰 Keyboards

14. /menu – Inline Keyboard

Buttons with callbacks
// Command: /menu
ctx.reply('Choose:', Markup.inlineKeyboard([
  [Markup.button.callback('🔔 Notify', 'notify'), Markup.button.callback('❓ Help', 'help')],
  [Markup.button.url('🌐 Website', 'https://runmybot.example')]
]));

// Handle callbacks
bot.action('notify', (ctx) => ctx.answerCbQuery('Enabled!'));
bot.action('help', (ctx) => ctx.editMessageText('Help opened.')); 

15. /replykbd – Reply Keyboard

Persistent keyboard under input
// Command: /replykbd
ctx.reply('Pick one:', Markup.keyboard([
  ['⭐ Star', '📜 Help'],
  ['ℹ️ Info']
]).resize());

16. /hidekbd – Hide Reply Keyboard

Remove custom keyboard
// Command: /hidekbd
ctx.reply('Keyboard hidden.', Markup.removeKeyboard());

17. /force – Force Reply

For quick prompt flows
// Command: /force
ctx.reply('What is your email?', { reply_markup: { force_reply: true } });

🎲 Polls & Fun

18. /dice – Dice

Random 🎲
// Command: /dice
ctx.replyWithDice();

19. /poll – Simple Poll

Anonymous off/on
// Command: /poll
ctx.replyWithPoll('Favorite language?', ['JS','Python','Go'], { is_anonymous:false });

20. /quiz – Quiz Poll

Right answer index + explanation
// Command: /quiz
ctx.replyWithQuiz('2 + 2 = ?', ['3','4','5'], { correct_option_id:1, explanation:'Basic math' });

📍 Location & Contacts

21. /loc – Send Location

Latitude & longitude
// Command: /loc
ctx.replyWithLocation(21.1702, 72.8311); // Surat, IN

22. /venue – Venue

Location + title & address
// Command: /venue
ctx.replyWithVenue(21.1702, 72.8311, 'RunMyBot HQ', 'Ring Road, Surat');

23. /contact – Contact

Share a phone contact
// Command: /contact
ctx.replyWithContact('+911234567890', 'Support', 'RunMyBot');

🗂️ Files & Albums

24. /album – Media Group

Send multiple photos as an album
// Command: /album
ctx.replyWithMediaGroup([
  { type:'photo', media:{url:'https://picsum.photos/600/400?1'} },
  { type:'photo', media:{url:'https://picsum.photos/600/400?2'} },
]);

25. /caption – Edit Caption

Edit last photo caption (store message_id yourself)
// Command: /caption
const sent = await ctx.replyWithPhoto({url:'https://picsum.photos/640/360'}, {caption:'Old'});
await ctx.telegram.editMessageCaption(ctx.chat.id, sent.message_id, undefined, 'New caption');

🛡️ Admin & Group Tools

26. /admins – List Admins

Works in groups/supergroups
// Command: /admins
const admins = await ctx.getChatAdministrators();
ctx.reply('Admins:\n' + admins.map(a => `• ${a.user.first_name}`).join('\n'));

27. /ban – Ban User (reply)

Reply to a user's message and run /ban (bot must be admin)
// Command: /ban
if (!ctx.message.reply_to_message) return ctx.reply('Reply to a user to ban');
const uid = ctx.message.reply_to_message.from.id;
try { await ctx.banChatMember(uid); ctx.reply('User banned.'); }
catch(e){ ctx.reply('Failed: ' + e.message); }

28. /pin – Pin (reply)

Pin a message in groups
// Command: /pin
if (!ctx.message.reply_to_message) return ctx.reply('Reply to pin');
try { await ctx.pinChatMessage(ctx.message.reply_to_message.message_id); ctx.reply('Pinned.'); }
catch(e){ ctx.reply('Failed: ' + e.message); }

🧿 Inline Mode

29. Inline Query – Echo Results

Enable inline mode in BotFather first
// In main file (not inside a command)
bot.on('inline_query', async (ctx) => {
  const q = ctx.inlineQuery.query || 'empty';
  await ctx.answerInlineQuery([
    { type:'article', id:'1', title:'Echo', input_message_content:{ message_text:q } },
  ], { cache_time: 0 });
});

💸 Payments

30. /pay – Send Invoice

Set provider token in BotFather → Payments
// Command: /pay
ctx.replyWithInvoice({
  title: 'Pro Plan', description: 'RunMyBot Pro (1 month)',
  payload: 'pro-001', provider_token: process.env.PAY_TOKEN || '',
  currency: 'INR', prices: [{ label:'Subscription', amount: 49900 }],
});

bot.on('pre_checkout_query', (ctx) => ctx.answerPreCheckoutQuery(true));
bot.on('successful_payment', (ctx) => ctx.reply('✅ Payment received!')); 

🧭 Multi‑Step Flow (Scenes/Wizard)

31. Simple 2‑Step Wizard

Collect user data across messages
// npm i telegraf @telegraf/session
const { Scenes, session } = require('telegraf');

const askName = new Scenes.BaseScene('askName');
askName.enter((ctx) => ctx.reply('Your name?'));
askName.on('text', (ctx) => { ctx.scene.state.name = ctx.message.text; return ctx.scene.enter('askEmail'); });

const askEmail = new Scenes.BaseScene('askEmail');
askEmail.enter((ctx) => ctx.reply('Your email?'));
askEmail.on('text', (ctx) => {
  ctx.scene.state.email = ctx.message.text;
  ctx.reply(`Saved: ${ctx.scene.state.name} & ${ctx.scene.state.email}`);
  return ctx.scene.leave();
});

const stage = new Scenes.Stage([askName, askEmail]);
bot.use(session());
bot.use(stage.middleware());

// Command: /register
ctx.scene.enter('askName');

🧱 Middleware & Filters

32. Logger Middleware

Log each update
// Global (top of file)
bot.use(async (ctx, next) => {
  console.log('Update', ctx.updateType);
  return next();
});

33. Hears Keyword

React to plain text
// Anywhere
bot.hears(/hello|hi/i, (ctx) => ctx.reply('Hello there!'));

34. Only Admin Guard

Restrict a handler to group admins
async function onlyAdmins(ctx, next){
  const me = await ctx.getChatMember(ctx.from.id);
  if(['administrator','creator'].includes(me.status)) return next();
  return ctx.reply('Admins only.');
}

// Command: /admin
onlyAdmins(ctx, () => ctx.reply('Secret admin thing…'));

🛰️ Webhook & Deploy

35. Express Webhook

For Render/Vercel/Cloud
// file: server.js
// npm i telegraf express body-parser
const { Telegraf } = require('telegraf');
const express = require('express');
const app = express();
const bot = new Telegraf(process.env.BOT_TOKEN || '');

app.use(bot.webhookCallback('/tg'));
bot.telegram.setWebhook((process.env.BASE_URL || 'https://example.com') + '/tg');

app.get('/', (_, res) => res.send('OK'));
app.listen(process.env.PORT || 3000, () => console.log('Webhook listening'));

🧪 Sample Bot Workflow

Goal: convert a free user to Pro. Flow = /start → /menu → Collect Email → Create Ticket → Offer Pay → Success

36. End‑to‑End Flow (compact)

Paste into your bot after basic setup
// 1) Start + Menu
bot.start((ctx) => ctx.reply('Welcome! Ready to level up?', Markup.inlineKeyboard([
  [Markup.button.callback('📬 Contact Support','support')],
  [Markup.button.callback('💎 Go Pro (₹499)','pro')]
])));

// 2) Support flow – collect email
bot.action('support', async (ctx) => {
  await ctx.answerCbQuery();
  await ctx.reply('Your email?', { reply_markup:{ force_reply:true } });
});

bot.on('message', async (ctx, next) => {
  if (ctx.message.reply_to_message && /Your email\?/i.test(ctx.message.reply_to_message.text)) {
    const email = ctx.message.text.trim();
    await ctx.reply(`Thanks! Ticket created for ${email}. Our team will reach out.`);
    // TODO: save to DB / send to webhook
    return;
  }
  return next();
});

// 3) Payment offer
bot.action('pro', async (ctx) => {
  await ctx.answerCbQuery();
  return ctx.replyWithInvoice({
    title:'RunMyBot Pro', description:'1 month access', payload:'pro-001',
    provider_token: process.env.PAY_TOKEN || '', currency:'INR',
    prices:[{label:'Pro Plan', amount:49900}],
  });
});

bot.on('pre_checkout_query', (ctx) => ctx.answerPreCheckoutQuery(true));

bot.on('successful_payment', (ctx) => ctx.reply('🎉 You are Pro now! Use /help to explore premium features.'));

🧰 Misc & Utilities

37. /joke – Random Joke

In‑memory list
// Command: /joke
const jokes = [
  'Why don’t scientists trust atoms? Because they make up everything!',
  'I would tell you a UDP joke, but you might not get it.'
];
ctx.reply(jokes[Math.floor(Math.random()*jokes.length)]);

38. /setcmds – Publish Bot Commands

So users see a command list in the app
// Command: /setcmds
await ctx.telegram.setMyCommands([
  { command:'start', description:'Start the bot' },
  { command:'help', description:'Get help' },
  { command:'info', description:'Your profile' },
]);
ctx.reply('Commands published.');

39. /forward – Forward Message

Forward a replied message to another chat
// Command: /forward
const targetChatId = ''; // e.g., your admin channel
if (!ctx.message.reply_to_message) return ctx.reply('Reply to a message to forward');
await ctx.telegram.forwardMessage(targetChatId, ctx.chat.id, ctx.message.reply_to_message.message_id);
ctx.reply('Forwarded.');

40. /whoami – Raw Update Debug

Inspect the incoming update
// Command: /whoami
ctx.reply('```\n' + JSON.stringify(ctx.update, null, 2) + '\n```', { parse_mode:'MarkdownV2' });

ℹ️ Notes

• Some actions require your bot to be admin (pin, delete, ban) in groups.
• For Inline Mode, enable via @BotFather → /setinline.
• For Payments, configure a payment provider token in @BotFather.
• When deploying with webhooks, do not call bot.launch() and set a fixed HTTPS URL.