Command Parsing and Validation¶
All commands are parsed by the pure-logic layer in internal/domain/command.go.
The package exports a small set of command structs - a FilterCommand, a
StopCommand. It also includes a few constants that represent the
supported commands. For now, all the commands live there since they're quite
simple and it doesn't make sense yet to split into additional separated
packages.
AI Prompt command¶
| Command | What it does | Example |
|---|---|---|
/prompt |
Send a message to the AI assistant. Starts a new conversation thread. | /prompt What is the capital of France? |
The /prompt command is parsed by ParsePromptCommand, which simply extracts everything after /prompt as the
user's message text. Unlike filter commands, /prompt does not go through token extraction or trigger validation - it
passes the raw message content to the AI client.
Thread continuations (replies to Patrizio's AI messages) are detected by isThreadContinuation in handler.go, not
by the command parser. When a message quotes a known conversation message, it is treated as a continuation without
requiring any command prefix.
Reaction based commands (aka Filters)¶
Here is the list of the current implemented filters (note this is not an usage guide, that one can be seen in the User guide):
| Command | What it does | Example |
|---|---|---|
/filter |
Create a filter. Trigger can be a word, phrase, or list. Reply can be text, reaction (react:emoji), or media. |
/filter hello Hi there! |
/stop |
Remove a single trigger from the current chat. | /stop hello |
/stopall |
Remove every filter in the chat. | /stopall |
/filters |
List all active filters. | /filters |
The parsing logic follows two steps:
- Token extraction - Handles quoted strings and comma-separated lists. Uses helpers like
parseNextTokenandparseCommaSeparatedTriggers. - Command construction - Builds a
FilterCommandorStopCommandstruct.
Because the parser is pure, it can be unit-tested in isolation. ValidateTrigger guarantees that trigger text contains
only Unicode letters, digits and spaces. When a trigger is stored it is normalised to lower-case. Incoming messages are
normalised with NormalizeMessage so that matching is case-insensitive.