CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-nonebot2

An asynchronous Python bot framework for building cross-platform chatbots with plugin architecture and adapter support.

Pending
Overview
Eval results
Files

message-matching.mddocs/

Message Matching

Specialized handlers for matching and responding to specific message patterns and commands. These provide convenient ways to create handlers for common message matching scenarios.

Capabilities

Command Matching

Match messages that start with command prefixes and handle command arguments.

def on_command(
    cmd: Union[str, tuple[str, ...]],
    rule: Optional[Rule] = None,
    aliases: Optional[set[Union[str, tuple[str, ...]]]] = None,
    force_whitespace: Optional[Union[str, bool]] = None,
    permission: Optional[Permission] = None,
    handlers: Optional[list[_Handler]] = None,
    temp: bool = False,
    expire_time: Optional[Union[datetime, timedelta]] = None,
    priority: int = 1,
    block: bool = False,
    state: Optional[T_State] = None
) -> type[Matcher]:
    """
    Create a command handler.

    Parameters:
    - cmd: Command name (str) or command tuple (for sub-commands)
    - rule: Additional rule for matching
    - aliases: Alternative command names
    - force_whitespace: Force whitespace after command
    - permission: Permission for handling command
    - handlers: List of handler functions
    - temp: Whether this is a temporary matcher
    - expire_time: When temporary matcher expires
    - priority: Handler priority (lower = higher priority)
    - block: Whether to block further handler execution
    - state: Initial state data

    Returns:
    type[Matcher]: Matcher class for command events
    """

Usage example:

import nonebot
from nonebot import on_command
from nonebot.adapters import Bot, Event
from nonebot.params import CommandArg

# Simple command
hello = on_command("hello")

@hello.handle()
async def handle_hello(bot: Bot, event: Event, args=CommandArg()):
    name = args.extract_plain_text().strip()
    if name:
        await bot.send(event, f"Hello, {name}!")
    else:
        await bot.send(event, "Hello, world!")

# Command with sub-commands
weather = on_command(("weather", "today"))

@weather.handle()
async def handle_weather_today(bot: Bot, event: Event):
    await bot.send(event, "Today's weather: Sunny")

# Command with aliases
ping = on_command("ping", aliases={"test", "status"})

@ping.handle()
async def handle_ping(bot: Bot, event: Event):
    await bot.send(event, "Pong!")

Shell Command Matching

Match commands with shell-style argument parsing.

def on_shell_command(
    cmd: Union[str, tuple[str, ...]],
    rule: Optional[Rule] = None,
    aliases: Optional[set[Union[str, tuple[str, ...]]]] = None,
    parser: Optional[ArgumentParser] = None,
    permission: Optional[Permission] = None,
    handlers: Optional[list[_Handler]] = None,
    temp: bool = False,
    expire_time: Optional[Union[datetime, timedelta]] = None,
    priority: int = 1,
    block: bool = False,
    state: Optional[T_State] = None
) -> type[Matcher]:
    """
    Create a shell command handler with argument parsing.

    Parameters:
    - cmd: Command name or tuple
    - rule: Additional rule for matching
    - aliases: Alternative command names
    - parser: ArgumentParser for parsing arguments
    - permission: Permission for handling command
    - handlers: List of handler functions
    - temp: Whether this is a temporary matcher
    - expire_time: When temporary matcher expires
    - priority: Handler priority (lower = higher priority)
    - block: Whether to block further handler execution
    - state: Initial state data

    Returns:
    type[Matcher]: Matcher class for shell command events
    """

Usage example:

import nonebot
from nonebot import on_shell_command
from nonebot.adapters import Bot, Event
from nonebot.params import ShellCommandArgs
from nonebot.rule import ArgumentParser

# Create argument parser  
parser = ArgumentParser()
parser.add_argument("--name", type=str, default="world")
parser.add_argument("--count", type=int, default=1)

# Create shell command
greet = on_shell_command("greet", parser=parser)

@greet.handle()
async def handle_greet(bot: Bot, event: Event, args=ShellCommandArgs()):
    name = args.name
    count = args.count
    
    for i in range(count):
        await bot.send(event, f"Hello, {name}!")

Text Pattern Matching

Match messages that start with, end with, or exactly match specific text.

def on_startswith(
    msg: Union[str, tuple[str, ...]],
    ignorecase: bool = False,
    rule: Optional[Rule] = None,
    permission: Optional[Permission] = None,
    handlers: Optional[list[_Handler]] = None,
    temp: bool = False,
    expire_time: Optional[Union[datetime, timedelta]] = None,
    priority: int = 1,
    block: bool = False,
    state: Optional[T_State] = None
) -> type[Matcher]:
    """
    Create handler for messages starting with specific text.

    Parameters:
    - msg: Text or tuple of texts to match at start
    - ignorecase: Whether to ignore case in matching
    - rule: Additional rule for matching
    - permission: Permission for handling messages
    - handlers: List of handler functions
    - temp: Whether this is a temporary matcher
    - expire_time: When temporary matcher expires
    - priority: Handler priority (lower = higher priority)
    - block: Whether to block further handler execution
    - state: Initial state data

    Returns:
    type[Matcher]: Matcher class for startswith events
    """
def on_endswith(
    msg: Union[str, tuple[str, ...]],
    ignorecase: bool = False,
    rule: Optional[Rule] = None,
    permission: Optional[Permission] = None,
    handlers: Optional[list[_Handler]] = None,
    temp: bool = False,
    expire_time: Optional[Union[datetime, timedelta]] = None,
    priority: int = 1,
    block: bool = False,
    state: Optional[T_State] = None
) -> type[Matcher]:
    """
    Create handler for messages ending with specific text.

    Parameters:
    - msg: Text or tuple of texts to match at end
    - ignorecase: Whether to ignore case in matching
    - rule: Additional rule for matching
    - permission: Permission for handling messages
    - handlers: List of handler functions
    - temp: Whether this is a temporary matcher
    - expire_time: When temporary matcher expires
    - priority: Handler priority (lower = higher priority)
    - block: Whether to block further handler execution
    - state: Initial state data

    Returns:
    type[Matcher]: Matcher class for endswith events
    """
def on_fullmatch(
    msg: Union[str, tuple[str, ...]],
    ignorecase: bool = False,
    rule: Optional[Rule] = None,
    permission: Optional[Permission] = None,
    handlers: Optional[list[_Handler]] = None,
    temp: bool = False,
    expire_time: Optional[Union[datetime, timedelta]] = None,
    priority: int = 1,
    block: bool = False,
    state: Optional[T_State] = None
) -> type[Matcher]:
    """
    Create handler for messages that exactly match specific text.

    Parameters:
    - msg: Text or tuple of texts to match exactly
    - ignorecase: Whether to ignore case in matching
    - rule: Additional rule for matching
    - permission: Permission for handling messages
    - handlers: List of handler functions
    - temp: Whether this is a temporary matcher
    - expire_time: When temporary matcher expires
    - priority: Handler priority (lower = higher priority)
    - block: Whether to block further handler execution
    - state: Initial state data

    Returns:
    type[Matcher]: Matcher class for fullmatch events
    """

Usage example:

import nonebot
from nonebot import on_startswith, on_endswith, on_fullmatch
from nonebot.adapters import Bot, Event
from nonebot.params import Startswith, Endswith, Fullmatch

# Match messages starting with text
starts_handler = on_startswith("prefix")

@starts_handler.handle()
async def handle_starts(bot: Bot, event: Event, matched=Startswith()):
    await bot.send(event, f"Matched prefix: {matched}")

# Match messages ending with text
ends_handler = on_endswith("suffix")

@ends_handler.handle()
async def handle_ends(bot: Bot, event: Event, matched=Endswith()):
    await bot.send(event, f"Matched suffix: {matched}")

# Match exact text
exact_handler = on_fullmatch("exact")

@exact_handler.handle()
async def handle_exact(bot: Bot, event: Event, matched=Fullmatch()):
    await bot.send(event, f"Exact match: {matched}")

Keyword Matching

Match messages containing specific keywords.

def on_keyword(
    *keywords: str,
    rule: Optional[Rule] = None,
    permission: Optional[Permission] = None,
    handlers: Optional[list[_Handler]] = None,
    temp: bool = False,
    expire_time: Optional[Union[datetime, timedelta]] = None,
    priority: int = 1,
    block: bool = False,
    state: Optional[T_State] = None
) -> type[Matcher]:
    """
    Create handler for messages containing keywords.

    Parameters:
    - *keywords: Keywords to search for in messages
    - rule: Additional rule for matching
    - permission: Permission for handling messages
    - handlers: List of handler functions
    - temp: Whether this is a temporary matcher
    - expire_time: When temporary matcher expires
    - priority: Handler priority (lower = higher priority)
    - block: Whether to block further handler execution
    - state: Initial state data

    Returns:
    type[Matcher]: Matcher class for keyword events
    """

Usage example:

import nonebot
from nonebot import on_keyword
from nonebot.adapters import Bot, Event
from nonebot.params import Keyword

# Match messages with keywords
keyword_handler = on_keyword("help", "assist", "support")

@keyword_handler.handle()
async def handle_keyword(bot: Bot, event: Event, matched=Keyword()):
    await bot.send(event, f"Detected keyword: {matched}")
    await bot.send(event, "How can I help you?")

Regular Expression Matching

Match messages using regular expressions for complex patterns.

def on_regex(
    pattern: Union[str, re.Pattern[str]],
    flags: Union[int, re.RegexFlag] = 0,
    rule: Optional[Rule] = None,
    permission: Optional[Permission] = None,
    handlers: Optional[list[_Handler]] = None,
    temp: bool = False,
    expire_time: Optional[Union[datetime, timedelta]] = None,
    priority: int = 1,
    block: bool = False,
    state: Optional[T_State] = None
) -> type[Matcher]:
    """
    Create handler for messages matching regular expressions.

    Parameters:
    - pattern: Regular expression pattern (str or compiled Pattern)
    - flags: Regular expression flags
    - rule: Additional rule for matching
    - permission: Permission for handling messages
    - handlers: List of handler functions
    - temp: Whether this is a temporary matcher
    - expire_time: When temporary matcher expires
    - priority: Handler priority (lower = higher priority)
    - block: Whether to block further handler execution
    - state: Initial state data

    Returns:
    type[Matcher]: Matcher class for regex events
    """

Usage example:

import nonebot
import re
from nonebot import on_regex
from nonebot.adapters import Bot, Event
from nonebot.params import RegexMatched, RegexStr, RegexGroup

# Match email addresses
email_pattern = r"([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})"
email_handler = on_regex(email_pattern)

@email_handler.handle()
async def handle_email(
    bot: Bot, 
    event: Event, 
    matched=RegexMatched(),
    email=RegexStr(0),
    username=RegexStr(1),
    domain=RegexStr(2)
):
    await bot.send(event, f"Found email: {email}")
    await bot.send(event, f"Username: {username}, Domain: {domain}")

# Match numbers with case-insensitive flag
number_handler = on_regex(r"number\s+(\d+)", flags=re.IGNORECASE)

@number_handler.handle()
async def handle_number(bot: Bot, event: Event, groups=RegexGroup()):
    number = groups[0]
    await bot.send(event, f"Number detected: {number}")

Types

Command Types

class CommandGroup:
    """Group related commands together."""
    
    def command(self, cmd: Union[str, tuple[str, ...]], **kwargs) -> type[Matcher]:
        """Create command in this group."""

class MatcherGroup:
    """Group related matchers together."""
    
    def on(self, **kwargs) -> type[Matcher]:
        """Create matcher in this group."""

Argument Parser

class ArgumentParser:
    """Extended argument parser for shell commands."""
    
    def add_argument(self, *args, **kwargs) -> None:
        """Add command line argument."""

class Namespace:
    """Argument namespace containing parsed arguments."""

Install with Tessl CLI

npx tessl i tessl/pypi-nonebot2

docs

adapters-drivers.md

bot-management.md

configuration.md

dependencies-parameters.md

event-handlers.md

framework-control.md

index.md

message-matching.md

plugin-system.md

tile.json