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
user: {
    name: string;
    id: number;
}
state: {
    name: string | undefined;
}