Overview
Command filters allow you to validate and match command arguments. These filters work in conjunction with the [CommandHandler] attribute to provide fine-grained control over command processing.
Argument Count
ArgumentCount
Filters messages where a command has a minimum number of arguments.
The minimum number of arguments required.
Example:
[CommandHandler("send")]
[ArgumentCount(2)] // Requires at least 2 arguments
public async Task HandleSend()
{
// Matches: /send user message
// Matches: /send user hello world
// Rejects: /send user
// Rejects: /send
}
Argument Content Matching
ArgumentStartsWith
Filters messages where a command argument starts with specific content.
The content that the command argument should start with.
comparison
StringComparison
default:"InvariantCulture"
The string comparison type to use for the check.
The index of the argument to check (0-based).
Example:
[CommandHandler("file")]
[ArgumentStartsWith("https://", index: 0)]
public async Task HandleFileUrl()
{
// Matches: /file https://example.com/doc.pdf
// Rejects: /file http://example.com/doc.pdf
// Rejects: /file document.pdf
}
ArgumentEndsWith
Filters messages where a command argument ends with specific content.
The content that the command argument should end with.
comparison
StringComparison
default:"InvariantCulture"
The string comparison type to use for the check.
The index of the argument to check (0-based).
Example:
[CommandHandler("download")]
[ArgumentEndsWith(".pdf", index: 0)]
public async Task HandlePdfDownload()
{
// Matches: /download document.pdf
// Matches: /download report.pdf
// Rejects: /download image.png
}
ArgumentContains
Filters messages where a command argument contains specific content.
The content that the command argument should contain.
comparison
StringComparison
default:"InvariantCulture"
The string comparison type to use for the check.
The index of the argument to check (0-based).
Example:
[CommandHandler("search")]
[ArgumentContains("@", index: 0)]
public async Task HandleEmailSearch()
{
// Matches: /search [email protected]
// Matches: /search [email protected]
// Rejects: /search username
}
ArgumentEquals
Filters messages where a command argument equals specific content.
The content that the command argument should equal.
comparison
StringComparison
default:"InvariantCulture"
The string comparison type to use for the check.
The index of the argument to check (0-based).
Example:
[CommandHandler("settings")]
[ArgumentEquals("reset", index: 0)]
public async Task HandleSettingsReset()
{
// Matches: /settings reset
// Rejects: /settings show
// Rejects: /settings Reset (case-sensitive by default)
}
[CommandHandler("settings")]
[ArgumentEquals("show", StringComparison.OrdinalIgnoreCase, index: 0)]
public async Task HandleSettingsShow()
{
// Matches: /settings show
// Matches: /settings SHOW
// Matches: /settings Show
}
Pattern Matching
ArgumentRegex
Filters messages where a command argument matches a regular expression pattern.
The regular expression pattern to match against the command argument.
options
RegexOptions
default:"None"
The regex options to use for the pattern matching.
The index of the argument to check (0-based).
Example:
using System.Text.RegularExpressions;
[CommandHandler("user")]
[ArgumentRegex(@"^\d{5,}$", index: 0)] // Match user IDs (5+ digits)
public async Task HandleUserById()
{
// Matches: /user 123456
// Matches: /user 987654321
// Rejects: /user john
// Rejects: /user 123 (too short)
}
[CommandHandler("email")]
[ArgumentRegex(@"^[\w\.-]+@[\w\.-]+\.\w+$", RegexOptions.IgnoreCase, index: 0)]
public async Task HandleEmail()
{
// Matches: /email [email protected]
// Matches: /email [email protected]
// Rejects: /email invalid-email
}
Command Aliases
CommandAlias
Filters messages based on command aliases, allowing handlers to respond to multiple command variations.
The command aliases to match against. Leading slashes are automatically removed.
Description
string
default:"no description provided"
The description of the command (0-256 characters). Set as a property after initialization.
Example:
[CommandAlias("help", "h", "?")]
public async Task HandleHelp()
{
// Matches: /help
// Matches: /h
// Matches: /?
await Bot.SendTextMessageAsync("Help menu...");
}
[CommandAlias("settings", "config", "cfg")]
public async Task HandleSettings()
{
// Matches: /settings
// Matches: /config
// Matches: /cfg
}
With Description:
var handler = new CommandAliasAttribute("start", "begin")
{
Description = "Start the bot and show welcome message"
};
Practical Examples
Validating File Extensions
[CommandHandler("convert")]
[ArgumentCount(1)]
[ArgumentRegex(@"\.(jpg|png|gif)$", RegexOptions.IgnoreCase, index: 0)]
public async Task HandleImageConvert()
{
// Matches: /convert photo.jpg
// Matches: /convert image.PNG
// Rejects: /convert document.pdf
}
Multi-Argument Validation
[CommandHandler("transfer")]
[ArgumentCount(2)]
[ArgumentRegex(@"^\d+$", index: 0)] // First arg must be numeric
[ArgumentStartsWith("@", index: 1)] // Second arg must be username
public async Task HandleTransfer()
{
// Matches: /transfer 100 @username
// Rejects: /transfer abc @username
// Rejects: /transfer 100 username
}
Subcommand Routing
[CommandHandler("admin")]
[ArgumentEquals("ban", index: 0)]
[ArgumentCount(2)]
public async Task HandleAdminBan()
{
// Matches: /admin ban @user
}
[CommandHandler("admin")]
[ArgumentEquals("unban", index: 0)]
[ArgumentCount(2)]
public async Task HandleAdminUnban()
{
// Matches: /admin unban @user
}
[CommandHandler("admin")]
[ArgumentEquals("list", index: 0)]
public async Task HandleAdminList()
{
// Matches: /admin list
}
Best Practices
-
Use the most specific filter: Choose
ArgumentEquals over ArgumentRegex when matching exact strings for better performance.
-
Check argument count first: Place
[ArgumentCount] before other argument filters to avoid null reference issues.
-
Index correctly: Remember that argument indices are 0-based and don’t include the command itself.
-
Use case-insensitive comparison: When appropriate, use
StringComparison.OrdinalIgnoreCase for user-friendly commands.
-
Combine with other filters: Mix command filters with chat or sender filters for precise routing:
[CommandHandler("admin")]
[ArgumentEquals("delete", index: 0)]
[ChatType(ChatType.Group)] // Only in groups
[FromUserId(123456)] // Only from specific admin
public async Task HandleAdminDelete() { }