-
Notifications
You must be signed in to change notification settings - Fork 0
Commands
A command is a special message that tells your bot to do something specific. Commands start with a prefix (like !) followed by the command name and optional arguments.
Let's break down this example command message:
!greet Alice! - The prefix that identifies this as a command greet - The command name that tells the bot what action to perform Alice - An argument (parameter) passed to the command
When a user sends this message, your bot:
- Recognizes the prefix !
- Looks for a command named greet
- Executes the command's function
- Passes Alice as a parameter to that function
Your bot receives ALL messages in rooms it's in, but only processes messages that start with the prefix as commands. Regular messages are ignored (unless you specifically handle them with event handlers, which are covered here).
Let's create a simple command that responds with "Pong π" when someone types !ping.
Commands are created using the @bot.command() decorator:
from matrix import Bot
bot = Bot(config="config.yaml")
@bot.command()
async def ping(ctx):
await ctx.reply("Pong π")
bot.start()Make your command clearer by adding a description:
@bot.command(description="Checks if the bot is responding")
async def ping(ctx):
await ctx.reply("Pong π")This description shows up in the help command when users type !help ping.
Sometimes you want the command name to be different from the function name:
@bot.command(name="hello", description="Greets you!")
async def greeting_function(ctx):
await ctx.reply("Hello! Welcome! π")Now users type !hello, but your function is named greeting_function.
As you saw, every command must have a ctx (context) parameter. The context is an object that contains everything you need to know about how the command was called:
- Who called the command
- Where it was called (which room)
- What arguments were provided
- How to respond to the command
@bot.command()
async def whoami(ctx):
# Who sent the command?
sender = ctx.sender # "@alice:example.com"
# What room are we in?
room_name = ctx.room_name # "General Chat"
room_id = ctx.room_id # "!abc123:example.com"
# What was the message?
message = ctx.body # "!whoami"
# Send all this info back
await ctx.reply(f"You are {sender} in {room_name} ({room_id}) and your message was {message}")| Attribute | Description | Example |
|---|---|---|
ctx.sender |
User ID who sent the command | "@alice:example.com" |
ctx.room_id |
Unique room identifier | "!abc123:example.com" |
ctx.room_name |
Human-readable room name | "General Chat" |
ctx.body |
The full message text | "!greet Alice" |
ctx.args |
List of arguments after command | ["Alice"] |
ctx.command |
The Command object itself | Command(name="greet") |
ctx.bot |
The bot instance | Bot(...) |
ctx.logger |
Logger for this room | Logger(...) |
The most common thing you'll do with context is send responses:
@bot.command()
async def echo(ctx):
await ctx.reply(f"You said: {ctx.body}")Some commands might need additional information from the user. These are called parameters or arguments.
Add parameters to your command function after ctx:
@bot.command(description="Greets a specific person")
async def greet(ctx, name: str):
await ctx.reply(f"Hello, {name}!")Usage: !greet Alice β Bot responds: Hello, Alice!
Type hints tell commands what type of data to expect and how to convert the text into that type.
@bot.command()
async def example(ctx, text: str, number: int, decimal: float):
await ctx.reply(f"Text: {text}, Number: {number}, Decimal: {decimal}")Usage: !example hello 42 3.14
Matrix.py Automatically converts:
- "hello" stays as string β "hello"
- "42" converts to int β 42
- "3.14" converts to float β 3.14
Sometimes you want a parameter to be optional:
@bot.command(description="Greets someone, or everyone")
async def greet(ctx, name: str = "everyone"):
await ctx.reply(f"Hello, {name}!")Usage:
-
!greet Aliceβ "Hello, Alice! π" -
!greetβ "Hello, everyone! π"
What if you want to accept any number of arguments?
@bot.command(description="Joins words together")
async def join(ctx, *words: str):
# words will be a tuple of all arguments
result = " ".join(words)
await ctx.reply(result)Usage: !join Hello world from Matrix β "Hello world from Matrix"
If a required parameter is missing, Matrix.py raises a MissingArgumentError:
@bot.command()
async def divide(ctx, a: int, b: int):
result = a / b
await ctx.reply(f"{a} / {b} = {result}")Usage: !divide 10 β Error! Missing parameter b