Skip to content

Filter Combinators

Filter combinators allow you to compose complex routing conditions using and(), or(), and not() logic — combined with 20+ built-in predicates.

Quick Start

typescript
import { Bot, and, or, not, isPrivate, isGroup, isAdmin, hasText, hasPhoto } from 'vibegram';

// Only respond to text in private chats
bot.on('message', and(isPrivate, hasText), async (ctx, next) => {
    console.log('Private text message');
    await next();
});

// Admin-only command in groups
bot.command('ban', and(isGroup, isAdmin()), async (ctx) => {
    await ctx.reply('Admin action executed.');
});

Combinators

FunctionDescription
and(...filters)All filters must pass
or(...filters)At least one filter must pass
not(filter)Inverts the filter

Built-in Predicates

Chat Type

PredicateDescription
isPrivatePrivate (DM) chat
isGroupGroup or supergroup
isSupergroupSupergroup only
isChannelChannel post

User Type

PredicateDescription
isBotMessage from a bot
isHumanMessage from a real user
isUser(...ids)Specific user IDs
isAdmin()Chat admin or creator (async)

Content Type

PredicateDescription
hasTextMessage contains text
hasPhotoMessage contains photo
hasDocumentMessage contains document
hasVideoMessage contains video
hasAudioMessage contains audio
hasVoiceMessage contains voice note
hasStickerMessage contains sticker
hasAnimationMessage contains GIF
hasLocationMessage contains location
hasContactMessage contains contact

Message Properties

PredicateDescription
isForwardedMessage is forwarded
isReplyMessage is a reply
isCallbackQueryUpdate is a callback query
isInlineQueryUpdate is an inline query

Custom Predicates

FactoryDescription
isChat(...ids)Specific chat IDs
hasTextContaining(str)Text or caption contains substring

Examples

typescript
// Photos or videos from non-bots
bot.on('message', and(not(isBot), or(hasPhoto, hasVideo)), ctx => {
    ctx.reply('Media received from a real user.');
});

// VIP-only command
const VIP_IDS = [123456, 789012];
bot.command('vip', isUser(...VIP_IDS), ctx => {
    ctx.reply('Welcome, VIP!');
});

// Admin commands only in supergroups
bot.command('settings', and(isSupergroup, isAdmin()), ctx => {
    ctx.reply('Group settings panel.');
});

INFO

isAdmin() makes an API call to getChatMember — consider using the API Cache middleware to avoid redundant calls.

Released under the ISC License.