Skip to main content

Overview

Chat filters allow you to route messages based on properties of the chat where the message was sent. These filters help you create chat-specific handlers for different chat types, specific chats, or chat characteristics.

Chat Type

ChatType

Filters messages sent in chats of a specific type.
type
ChatType
The specific chat type to match.
flags
ChatTypeFlags
Multiple chat types using flags (alternative constructor).
Available Chat Types:
  • ChatType.Private - Direct messages with users
  • ChatType.Group - Regular groups
  • ChatType.Supergroup - Supergroups
  • ChatType.Channel - Channels
Example:
[CommandHandler("start")]
[ChatType(ChatType.Private)]
public async Task HandlePrivateStart()
{
    // Only executes in private chats
    await Bot.SendTextMessageAsync("Welcome to private chat!");
}

[CommandHandler("stats")]
[ChatType(ChatType.Group)]
public async Task HandleGroupStats()
{
    // Only executes in groups
    await Bot.SendTextMessageAsync("Group statistics...");
}

[CommandHandler("broadcast")]
[ChatType(ChatType.Channel)]
public async Task HandleChannelBroadcast()
{
    // Only executes in channels
}
Using Flags for Multiple Types:
[CommandHandler("help")]
[ChatType(ChatTypeFlags.Group | ChatTypeFlags.Supergroup)]
public async Task HandleGroupHelp()
{
    // Executes in both regular groups and supergroups
}

Chat Identification

ChatId

Filters messages sent in a specific chat by its ID.
id
long
required
The chat ID to match.
Example:
[ChatId(-1001234567890)]
public async Task HandleSpecificGroup()
{
    // Only executes in the chat with this specific ID
    await Bot.SendTextMessageAsync("This is our main group!");
}

[CommandHandler("admin")]
[ChatId(-1001234567890)]
public async Task HandleAdminInMainGroup()
{
    // Admin command only works in specific group
}
Finding Chat IDs:
public async Task LogChatId(Update update)
{
    var chatId = update.Message?.Chat.Id;
    Console.WriteLine($"Chat ID: {chatId}");
    // Use this ID in your ChatId filters
}

ChatUsername

Filters messages based on the chat’s username.
userName
string
required
The chat username to match (without @).
comparison
StringComparison
default:"InvariantCulture"
The string comparison method.
Example:
[ChatUsername("myofficialgroup")]
public async Task HandleOfficialGroup()
{
    // Only executes in @myofficialgroup
}

[ChatUsername("support", StringComparison.OrdinalIgnoreCase)]
public async Task HandleSupportChat()
{
    // Matches @support, @Support, @SUPPORT, etc.
}

Chat Properties

ChatTitle

Filters messages based on the chat’s title.
title
string
required
The chat title to match.
comparison
StringComparison
default:"InvariantCulture"
The string comparison method.
Example:
[ChatTitle("Development Team")]
public async Task HandleDevTeam()
{
    // Only executes in chats titled "Development Team"
}

[ChatTitle("support", StringComparison.OrdinalIgnoreCase)]
public async Task HandleSupportTitle()
{
    // Matches chats with "support", "Support", "SUPPORT", etc. in title
}
Note: Chat titles can be changed by administrators, so this filter is less reliable than ChatId for identifying specific chats.

ChatName

Filters messages based on the chat’s name (first name and optionally last name for private chats).
firstName
string
required
The first name to match.
lastName
string
The last name to match (optional).
comparison
StringComparison
default:"InvariantCulture"
The string comparison method.
Example:
[ChatName("John", "Doe")]
public async Task HandleJohnDoe()
{
    // Matches private chats with user "John Doe"
}

[ChatName("Support")]
public async Task HandleSupportName()
{
    // Matches chats with first name "Support"
}

[ChatName("Alice", null, StringComparison.OrdinalIgnoreCase)]
public async Task HandleAlice()
{
    // Matches "Alice", "alice", "ALICE", etc.
}

ChatIsForum

Filters messages sent in forum chats (supergroups with topics enabled). Example:
[ChatIsForum]
public async Task HandleForumMessage()
{
    // Only executes in forum chats
    await Bot.SendTextMessageAsync("This is a forum!");
}

[CommandHandler("topic")]
[ChatIsForum]
public async Task HandleTopicCommand()
{
    // Topic-related command only available in forums
}

Practical Examples

Environment-Specific Chats

[ChatId(-1001111111111)]  // Production chat
[IsReleaseEnvironment]
public async Task HandleProductionAlerts()
{
    // Production alerts only in production chat
}

[ChatId(-1002222222222)]  // Testing chat
[IsDebugEnvironment]
public async Task HandleTestAlerts()
{
    // Test alerts only in test chat
}

Multi-Chat Bot

[CommandHandler("start")]
[ChatType(ChatType.Private)]
public async Task HandlePrivateStart()
{
    await Bot.SendTextMessageAsync(
        "Welcome! Use /help to see available commands."
    );
}

[CommandHandler("start")]
[ChatType(ChatType.Group)]
public async Task HandleGroupStart()
{
    await Bot.SendTextMessageAsync(
        "Hello everyone! I'm ready to help this group."
    );
}

[CommandHandler("start")]
[ChatType(ChatType.Channel)]
public async Task HandleChannelStart()
{
    await Bot.SendTextMessageAsync(
        "Bot activated for this channel."
    );
}

Admin Panel in Specific Group

[CommandHandler("stats")]
[ChatId(-1001234567890)]  // Admin group ID
[FromUserId(123456)]      // Admin user ID
public async Task ShowDetailedStats()
{
    // Detailed stats only in admin group, only for admin
    await SendStatistics();
}

[CommandHandler("ban")]
[ChatId(-1001234567890)]
[FromUserId(123456)]
public async Task HandleBanCommand()
{
    // Ban command only works in admin group
}

Forum-Specific Features

[CommandHandler("newtopic")]
[ChatIsForum]
public async Task CreateNewTopic()
{
    // Create topic only in forums
    await Bot.CreateForumTopic(ChatId, "New Topic");
}

[TextContains("thread")]
[ChatIsForum]
public async Task HandleThreadMention()
{
    // React to thread mentions in forums
}

Official Groups Verification

private readonly HashSet<long> officialGroupIds = new()
{
    -1001234567890,
    -1009876543210,
    -1005555555555
};

[CommandHandler("verify")]
public async Task HandleVerify()
{
    var chatId = Update.Message.Chat.Id;
    
    if (officialGroupIds.Contains(chatId))
    {
        await Bot.SendTextMessageAsync("✓ This is an official group");
    }
    else
    {
        await Bot.SendTextMessageAsync("⚠ This is not an official group");
    }
}

// Or use multiple filters:
[CommandHandler("official")]
[ChatId(-1001234567890)]
public async Task HandleOfficialGroup1() 
{
    await Bot.SendTextMessageAsync("Official group verified!");
}

Combining Chat and User Filters

[ChatType(ChatType.Group)]
[FromPremiumUser]
public async Task HandlePremiumUserInGroup()
{
    // Special features for premium users in groups
}

[ChatIsForum]
[NotFromBot]
public async Task HandleHumanForumPost()
{
    // Only process human messages in forums
}

Best Practices

  1. Use ChatId for specific chats: When you need to target a specific chat, prefer [ChatId] over [ChatTitle] or [ChatUsername] as it’s more reliable.
  2. Handle multiple chat types gracefully: Create separate handlers for different chat types rather than using complex branching logic.
  3. Combine with permission checks: When filtering by chat, also consider filtering by user permissions:
[ChatId(-1001234567890)]
[FromUserId(123456)]  // Only specific admin
public async Task HandleSensitiveCommand() { }
  1. Log chat information during development: Log chat IDs and properties to help configure your filters:
public async Task LogChatInfo(Update update)
{
    var chat = update.Message?.Chat;
    Console.WriteLine($"Chat ID: {chat.Id}");
    Console.WriteLine($"Chat Type: {chat.Type}");
    Console.WriteLine($"Chat Title: {chat.Title}");
    Console.WriteLine($"Chat Username: {chat.Username}");
}
  1. Consider forum topics: When working with forums, remember that messages can belong to different topics within the same chat.

Chat Type Flags

When using ChatTypeFlags, you can combine multiple types:
// Accept both group types
ChatTypeFlags.Group | ChatTypeFlags.Supergroup

// Accept all except private
ChatTypeFlags.Group | ChatTypeFlags.Supergroup | ChatTypeFlags.Channel

Build docs developers (and LLMs) love