Skip to content

Начало работы

Создайте своего первого Telegram бота менее чем за минуту — типобезопасно, на любом рантайме, с богатой экосистемой плагинов.

1. Получите токен бота

Откройте @BotFather в Telegram, отправьте /newbot и следуйте инструкциям. Вы получите токен вида:

110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw

2. Создайте проект

Одна команда настраивает всё — TypeScript, линтинг, ORM, плагины, Docker — на ваш выбор.

::: pm-create gramio@latest ./bot :::

Что можно выбрать в генераторе?

3. Запустите разработку

sh
cd bot && npm run dev
sh
cd bot && yarn run dev
sh
cd bot && pnpm run dev
sh
cd bot && bun run dev

Бот работает и перезапускается при изменениях. Готово. Теперь посмотрим, что можно с этим сделать.


Как выглядит GramIO

Обработка команд

ts
import { Bot } from "gramio";

const bot = new Bot(process.env.BOT_TOKEN as string)
    .command("start", (ctx) => ctx.send("Привет! 👋"))
    .command("help", (ctx) => ctx.send("Вот что я умею..."))
    .onStart(({ info }) => console.log(`Запущен как @${info.username}`));

bot.start();

Форматирование сообщений

Никакого parse_mode — GramIO использует тегированные шаблонные строки, которые автоматически создают корректные объекты MessageEntity:

ts
import { Bot, format, bold, italic, link, code } from "gramio";

const bot = new Bot(process.env.BOT_TOKEN as string)
    .command("start", (ctx) =>
        ctx.send(
            format`${bold`Добро пожаловать!`}
            Загляните на ${link("GramIO", "https://gramio.dev")} — ${italic("типобезопасно до последней строчки")}.`
        )
    );

bot.start();

Создание клавиатур

Удобный цепочный API для инлайн и reply-клавиатур:

ts
import { Bot, InlineKeyboard } from "gramio";

const bot = new Bot(process.env.BOT_TOKEN as string)
    .command("menu", (ctx) =>
        ctx.send("Что вы хотите сделать?", {
            reply_markup: new InlineKeyboard()
                .text("О проекте", "about")
                .url("GitHub", "https://github.com/gramiojs/gramio")
                .row()
                .text("Настройки ⚙️", "settings"),
        })
    );

bot.start();

Типобезопасное расширение контекста через derive

Добавляйте свои данные в каждый обработчик — без приведения типов, полная типизация:

ts
import { Bot } from "gramio";
import { db } from "./db";

const bot = new Bot(process.env.BOT_TOKEN as string)
    .derive("message", async (ctx) => ({
        user: await db.getUser(ctx.from!.id),
    }))
    .on("message", (ctx) => {
        ctx.user;
        //
        //
        //
        //
        return ctx.send(`Привет, ${ctx.user.name}!`);
    });

bot.start();

Конвейер мидлваров — Composer

Bot расширяет Composer — цепочный типобезопасный конвейер обработки обновлений. Каждый метод обогащает контекст и возвращает обновлённый тип, поэтому вся цепочка всегда полностью типизирована.

Composer также существует как отдельный класс — его можно импортировать и использовать независимо от Bot. Это важно, когда проект начинает расти:

МетодЧто делает
use(ctx, next)Сырой мидлвар — вызовите next() чтобы продолжить
derive(fn)Асинхронное обогащение контекста на каждый запрос
decorate(obj)Статическое обогащение при запуске — без накладных расходов
guard(fn)Продолжить только если предикат вернул true
on(event, fn)Обработать конкретный тип обновления
extend(composer)Встроить другой композер — унаследовав его полные типы

Продакшн-паттерн: общий плагинный композер

В реальном проекте регистрируйте все плагины один раз в общем Composer, а затем расширяйте его в каждом файле с фичами. Каждый обработчик становится чистым Composer — без Bot, без токена, легко тестируется:

ts
// src/plugins/index.ts
import { Composer } from "gramio";
import { scenes } from "@gramio/scenes";
import { session } from "@gramio/session";
import { greetingScene } from "../scenes/greeting.ts";

export const composer = new Composer()
    .extend(scenes([greetingScene]))
    .extend(session());
ts
// src/features/start.ts
import { Composer } from "gramio";
import { composer } from "../plugins/index.ts";

export const startFeature = new Composer()
    .extend(composer) // ← наследует все типы плагинов
    .command("start", (ctx) => {
        ctx.scene; // ✅ полная типизация — без Bot, без токена
        return ctx.scene.enter(greetingScene);
    });
ts
// src/index.ts
import { Bot } from "gramio";
import { composer } from "./plugins/index.ts";
import { startFeature } from "./features/start.ts";

const bot = new Bot(process.env.BOT_TOKEN as string)
    .extend(composer)      // плагины
    .extend(startFeature); // обработчики фич

bot.start();

Почему это работает

Composer передаёт свои типы через каждый .extend(). Когда startFeature расширяет composer, TypeScript видит все свойства, добавленные плагинами — ctx.scene, ctx.session и т.д. — без приведения типов и ручных аннотаций.

Расширение плагинами через .extend()

Плагины подключаются через .extend(). Они могут добавлять новые свойства в контекст, регистрировать обработчики и встраиваться в жизненный цикл — всё с полной типизацией.

Пример подключения Scenes для многошаговых диалогов:

::: pm-add @gramio/scenes :::

ts
import { Bot } from "gramio";
import { scenes, Scene } from "@gramio/scenes";

const registrationScene = new Scene("registration")
    .step("message", (ctx) => {
        if (ctx.scene.step.firstTime) return ctx.send("Как вас зовут?");
        return ctx.scene.update({ name: ctx.text });
    })
    .step("message", (ctx) => {
        ctx.scene.state;
        //
        //
        //
        //
        return ctx.send(`Приятно познакомиться, ${ctx.scene.state.name}!`);
    });

const bot = new Bot(process.env.BOT_TOKEN as string)
    .extend(scenes([registrationScene]))
    .command("start", (ctx) => ctx.scene.enter(registrationScene));

bot.start();

Каждый .step() срабатывает на следующее подходящее обновление от того же пользователя. Состояние сохраняется между шагами и полностью типизировано.


Официальные плагины

Расширяйте бота первоклассными плагинами, которые работают бесшовно:

ПлагинЧто делает
SessionСостояние пользователя между сообщениями
ScenesМногошаговые диалоги и визарды
I18nИнтернационализация на базе Fluent
AutoloadАвтоимпорт обработчиков из файловой системы
Auto-retryАвтоматический повтор при rate-limit ошибках
Media-cacheКэширование file_id загруженных файлов
Media-groupОбработка альбомов как одного события
ViewsJSX-рендеринг сообщений
PromptОжидание следующего сообщения пользователя
OpenTelemetryТрассировка и метрики
SentryОтслеживание ошибок и мониторинг

Смотреть все плагины →


Ручная установка

Предпочитаете настроить всё самостоятельно?

::: pm-add gramio :::

Создайте src/index.ts:

ts
import { Bot } from "gramio";

const bot = new Bot(process.env.BOT_TOKEN as string)
    .command("start", (ctx) => ctx.send("Привет! 👋"))
    .onStart(console.log);

bot.start();
ts
import { Bot } from "jsr:@gramio/core";

const bot = new Bot(process.env.BOT_TOKEN as string)
    .command("start", (ctx) => ctx.send("Привет! 👋"))
    .onStart(console.log);

bot.start();

Запустите:

bash
npx tsx ./src/index.ts
bash
bun ./src/index.ts
bash
deno run --allow-net --allow-env ./src/index.ts