Начало работы
Создайте своего первого Telegram бота менее чем за минуту — типобезопасно, на любом рантайме, с богатой экосистемой плагинов.
1. Получите токен бота
Откройте @BotFather в Telegram, отправьте /newbot и следуйте инструкциям. Вы получите токен вида:
110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw2. Создайте проект
Одна команда настраивает всё — TypeScript, линтинг, ORM, плагины, Docker — на ваш выбор.
::: pm-create gramio@latest ./bot :::
Что можно выбрать в генераторе?
- ORM — Prisma, Drizzle
- Линтеры — Biome, ESLint (с автонастройкой нужных плагинов)
- Официальные плагины — Scenes, Session, I18n, Autoload, Prompt, Auto-retry, Media-cache, Media-group
- Другое — Dockerfile + docker-compose, Husky git-хуки, Jobify (обёртка для BullMQ), хранилища GramIO
3. Запустите разработку
cd bot && npm run devcd bot && yarn run devcd bot && pnpm run devcd bot && bun run devБот работает и перезапускается при изменениях. Готово. Теперь посмотрим, что можно с этим сделать.
Как выглядит GramIO
Обработка команд
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:
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-клавиатур:
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
Добавляйте свои данные в каждый обработчик — без приведения типов, полная типизация:
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, без токена, легко тестируется:
// 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());// 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);
});// 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 :::
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 | Обработка альбомов как одного события |
| Views | JSX-рендеринг сообщений |
| Prompt | Ожидание следующего сообщения пользователя |
| OpenTelemetry | Трассировка и метрики |
| Sentry | Отслеживание ошибок и мониторинг |
Ручная установка
Предпочитаете настроить всё самостоятельно?
::: pm-add gramio :::
Создайте src/index.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();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();Запустите:
npx tsx ./src/index.tsbun ./src/index.tsdeno run --allow-net --allow-env ./src/index.ts