Skip to content

Фильтры

UNRELEASED

Система фильтров находится в ветке main и ещё не включена в релизную версию. API может измениться до стабильного релиза.

Система фильтров GramIO позволяет применять типобезопасные предикаты к контексту — как третий аргумент в bot.on(event, filter, handler), так и в виде filter-only вызова .on(filter, handler) без указания имени события — GramIO сам определяет совместимые события по форме предиката.

Filter-Only .on() — без имени события

При стандартном .on(event, handler) вы явно указываете событие. С filter-only перегрузкой имя пропускается — GramIO выводит совместимые события из формы предиката:

ts
import { Bot } from "gramio";

const bot = new Bot(process.env.BOT_TOKEN!);

// Булев фильтр — срабатывает на любом апдейте, где ctx содержит text
bot.on(
    (ctx) => "text" in ctx && ctx.text?.startsWith("!"),
    (ctx) => {
        ctx.send("Команда получена!");
    },
);

// Type-narrowing предикат — сужает тип контекста в обработчике
bot.on(
    (ctx): ctx is { text: string } => typeof (ctx as any).text === "string",
    (ctx) => {
        ctx.text; // string — не string | undefined
    },
);

Инлайн-фильтр на именованном событии

Фильтр можно передать вторым аргументом в .on() с именем события:

ts
bot.on(
    "message",
    (ctx) => ctx.text?.startsWith("/"),
    (ctx) => {
        // только сообщения, начинающиеся с "/"
    },
);

// Type-narrowing инлайн-фильтр
bot.on(
    "message",
    (ctx): ctx is typeof ctx & { text: string } => typeof ctx.text === "string",
    (ctx) => {
        ctx.text; // string
    },
);

Standalone предикаты

Импортируйте из gramio и передавайте в .on() или .guard():

ts
import { filters } from "gramio";

Фильтры содержимого сообщения

ФильтрСужает до / Проверяет
filters.replyСообщение с reply_to_message
filters.entitiesСообщение с entities
filters.captionEntitiesСообщение с caption_entities
filters.quoteСообщение с цитатой (quote)
filters.viaBotОтправлено через бота (via_bot)
filters.linkPreviewЕсть link_preview_options
filters.startPayload/start с deep-link payload
filters.authorSignatureЕсть author_signature
filters.mediaGroupСообщение в медиагруппе
filters.venueСообщение — место
ts
bot.on("message", filters.reply, (ctx) => {
    ctx.replyMessage; // гарантированно присутствует
});

bot.on("message", filters.startPayload, (ctx) => {
    // /start с deep-link payload
});

Фильтры отправителя и чата

ФильтрОписание
filters.hasFromАпдейт содержит поле from
filters.isBotfrom.is_bot === true
filters.isPremiumfrom.is_premium === true
filters.isForumЧат является форумом
filters.serviceСлужебное сообщение
filters.topicMessageСообщение в топике форума
filters.mediaSpoilerМедиа со спойлером
filters.giveawayСообщение с розыгрышем
filters.gameСообщение с игрой
filters.storyСообщение — история
filters.effectIdЕсть эффект сообщения

filters.forwardOrigin(type?) — сужение по источнику пересылки

Без аргумента матчит любое пересланное сообщение. С аргументом сужает тип forwardOrigin:

ts
// Любое пересланное сообщение
bot.on("message", filters.forwardOrigin(), (ctx) => {
    ctx.forwardOrigin; // MessageOrigin (union всех типов)
});

// Сужение до конкретного типа
bot.on("message", filters.forwardOrigin("user"), (ctx) => {
    ctx.forwardOrigin; // MessageOriginUser
    ctx.forwardOrigin.sender_user; // TelegramUser
});

bot.on("message", filters.forwardOrigin("channel"), (ctx) => {
    ctx.forwardOrigin; // MessageOriginChannel
    ctx.forwardOrigin.chat; // TelegramChat
    ctx.forwardOrigin.message_id; // number
});

Доступные типы: "user" | "hidden_user" | "chat" | "channel"

filters.senderChat(type?) — сужение по чату-отправителю

ts
// Любое сообщение от анонимного администратора или канала
bot.on("message", filters.senderChat(), (ctx) => {
    ctx.senderChat; // TelegramChat
});

// Сужение до конкретного типа чата
bot.on("message", filters.senderChat("channel"), (ctx) => {
    ctx.senderChat; // TelegramChat & { type: "channel" }
});

Композиция фильтров

Фильтры — это обычные функции. Компонуйте их логическими операторами:

ts
const isPremiumAdmin = (ctx: any) =>
    filters.isPremium(ctx) &&
    filters.hasFrom(ctx) &&
    ctx.from.status === "administrator";

bot.on("message", isPremiumAdmin, handler);

Type-Narrowing guard()

guard() с type predicate сужает TOut для всех downstream обработчиков в цепочке:

ts
const bot = new Bot(process.env.BOT_TOKEN!);

bot.guard(
    (ctx): ctx is typeof ctx & { text: string } => typeof ctx.text === "string",
).on("message", (ctx) => {
    ctx.text; // string — сужено для всех обработчиков после guard
});

Без type predicate (булев guard) работает как шлюз, блокирующий цепочку при false, но не сужающий типы.

Смотри также