migrate from telegraf

telegraf and yaebal both feel like bot frameworks, but yaebal uses named bot api params, typed filter queries, and context additions that flow through the composer chain.

initialization

init.ts
// telegraf
import { Telegraf } from "telegraf";
const bot = new Telegraf(process.env.BOT_TOKEN!);
bot.launch();

// yaebal
import { createBot } from "yaebal";
const bot = createBot(process.env.BOT_TOKEN!);
await bot.start();

handlers

handlers.ts
// telegraf
bot.start((ctx) => ctx.reply("hello"));
bot.on("text", (ctx) => ctx.reply(ctx.message.text));
bot.action("ok", (ctx) => ctx.answerCbQuery("ok"));

// yaebal
bot.command("start", (ctx) => ctx.reply("hello"));
bot.on("message:text", (ctx) => ctx.reply(ctx.text));
bot.callbackQuery("ok", (ctx) => ctx.answerCallbackQuery({ text: "ok" }));

api calls

api.ts
// telegraf
await ctx.telegram.sendMessage(chatId, "hello");
await ctx.replyWithPhoto("file_id");

// yaebal
await ctx.api.sendMessage({ chat_id: chatId, text: "hello" });
await ctx.sendPhoto("file_id");

keyboards

keyboard.ts
// telegraf
Markup.inlineKeyboard([[Markup.button.callback("yes", "yes")]]);

// yaebal
new InlineKeyboard().text("yes", "yes");

sessions

session.ts
// telegraf often uses ctx.session through middleware

// yaebal
const bot = createBot(token)
  .install(session({ initial: () => ({ count: 0 }) }))
  .command("count", (ctx) => ctx.reply(String(++ctx.session.count)));

webhooks

webhook.ts
// yaebal node http
import { createServer } from "node:http";
import { nodeWebhookCallback } from "@yaebal/core/node";

createServer(nodeWebhookCallback(bot, { secretToken: process.env.SECRET })).listen(8080);

mapping table

telegrafyaebal
bot.start(handler)bot.command("start", handler)
bot.on("text")bot.on("message:text")
bot.action(data)bot.callbackQuery(data)
ctx.telegramctx.api
ctx.replyWithPhotoctx.sendPhoto
Markup.inlineKeyboardInlineKeyboard

migration checklist

  • replace positional api calls with named param objects.
  • replace action handlers with callbackQuery.
  • replace context augmentation with typed plugins or derive/decorate.
  • use @yaebal/test to pin behavior before changing production handlers.
  • choose webhookCallback, nodeWebhookCallback, or @yaebal/web based on runtime.