Skip to content

GramIOСоздавайте Telegram ботов правильно.

Типобезопасно · Мультирантайм · Расширяемо

Посмотрите на деле

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

const bot = new Bot(process.env.BOT_TOKEN as string)
    .command("start", (ctx) =>
        ctx.send(
            format`${bold`Привет, ${ctx.from?.firstName ?? "незнакомец"}!`}

Добро пожаловать в ${link("GramIO", "https://gramio.dev")} — создавайте Telegram-ботов правильно.`,
        ),
    )
    .onError(({ kind, error }) => console.error(kind, error))
    .start();
ts
import { Bot, InlineKeyboard, CallbackData } from "gramio";

const voteData = new CallbackData("vote").string("choice");

const bot = new Bot(process.env.BOT_TOKEN as string)
    .command("poll", (ctx) =>
        ctx.send("Нравится ли вам GramIO?", {
            reply_markup: new InlineKeyboard()
                .text("Да ✅", voteData.pack({ choice: "yes" }))
                .text("Конечно 🔥", voteData.pack({ choice: "yes2" })),
        }),
    )
    .callbackQuery(voteData, (ctx) => {
        ctx.queryData.choice; // ^? string
        return ctx.answer();
    })
    .start();
ts
import {
    defineI18n,
    type LanguageMap,
    type ShouldFollowLanguage,
} from "@gramio/i18n";
import { Bot, format, bold } from "gramio";

const en = {
    welcome: (name: string) => format`Hello, ${bold(name)}!`,
    items: (n: number) => `You have ${n} item${n === 1 ? "" : "s"}`,
} satisfies LanguageMap;

const ru = {
    welcome: (name: string) => format`Привет, ${bold(name)}!`,
    items: (n: number) => `У вас ${n} предмет${n === 1 ? "" : "ов"}`,
} satisfies ShouldFollowLanguage<typeof en>; // ключи и сигнатуры должны совпадать

const i18n = defineI18n({ primaryLanguage: "en", languages: { en, ru } });

const bot = new Bot(process.env.BOT_TOKEN as string)
    .derive((ctx) => ({
        t: i18n.buildT(ctx.from?.language_code ?? "en"),
    }))
    .command("start", (ctx) =>
        ctx.send(ctx.t("welcome", ctx.from?.firstName ?? "незнакомец")),
    )
    .start();
ts
import { Bot } from "gramio";
import { Scene, scenes } from "@gramio/scenes";
import { redisStorage } from "@gramio/storage-redis";
import { Redis } from "ioredis";

const registerScene = new Scene("register")
    .step("message", (ctx) => {
        if (ctx.scene.step.firstTime) return ctx.send("Как вас зовут?");
        return ctx.scene.update({ name: ctx.text });
    })
    .step("message", (ctx) => {
        if (ctx.scene.step.firstTime)
            return ctx.send(`Привет, ${ctx.scene.state.name}! Ваш email?`);
        return ctx.scene.update({ email: ctx.text });
    })
    .step("message", (ctx) =>
        ctx.send(
            `Зарегистрирован: ${ctx.scene.state.name} — ${ctx.scene.state.email} ✅`,
        ),
    );

const bot = new Bot(process.env.BOT_TOKEN as string)
    .extend(scenes([registerScene], { storage: redisStorage(new Redis()) }))
    .command("register", (ctx) => ctx.scene.enter(registerScene))
    .start();
ts
import { Bot } from "gramio";
import { Composer } from "@gramio/composer";

// Общий middleware — типизированный контекст доступен в каждом модуле
const withUser = new Composer()
    .derive(async (ctx) => ({
        user: await db.getUser(ctx.from?.id ?? 0),
    }))
    .as("scoped");

// Feature-модуль — guard и команды в одной цепочке
const adminRouter = new Composer()
    .extend(withUser)
    .guard((ctx) => ctx.user.role === "admin")
    .command("ban", (ctx) => ctx.send(`Заблокирован — ${ctx.user.name}`))
    .command("stats", (ctx) => ctx.send("Статистика..."));

const bot = new Bot(process.env.BOT_TOKEN as string)
    .extend(withUser) // ctx.user — типизирован везде ниже
    .extend(adminRouter) // withUser внутри → дедуплицируется, запускается один раз
    .command(
        "profile",
        (
            ctx, // без guard — выполняется для всех
        ) => ctx.send(`Привет, ${ctx.user.name}!`),
        //                  ^? полностью типизировано
    )
    .start();

Последние обновления

Bot API 9.5, дебют Rate Limiter, конвертер HTML в Telegram, суперсилы Composer — 23 февраля – 2 марта 2026

Поддержка Bot API 9.5 во всей экосистеме (теги участников, сущности date_time). Новый плагин @gramio/rate-limit с макросным троттлингом. @gramio/format v0.5.0 — htmlToFormattable(). @gramio/composer получает EventContextOf, ContextOf, defineComposerMethods и систему макросов.

Все обновления →

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

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

Полный гайд по началу работы →