Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/xmistt/rebootpy/llms.txt

Use this file to discover all available pages before exploring further.

Overview

rebootpy supports two types of messages:
  • Friend Messages - Direct messages between friends
  • Party Messages - Messages in party chat
Both message types share similar functionality but have different contexts.

Message Classes

FriendMessage

Represents a message from a friend. Attributes:
  • client - The client instance
  • author - The Friend who sent the message
  • content - The message text (up to 256 characters)
  • created_at - When the message was received (UTC datetime)

PartyMessage

Represents a message in party chat. Attributes:
  • client - The client instance
  • author - The PartyMember who sent the message
  • content - The message text (up to 256 characters)
  • party - The ClientParty where the message was sent
  • created_at - When the message was received (UTC datetime)

Receiving Messages

Friend Messages

@client.event
async def event_friend_message(message):
    print(f'{message.author.display_name}: {message.content}')
    print(f'Received at: {message.created_at}')

Party Messages

@client.event
async def event_party_message(message):
    print(f'[Party] {message.author.display_name}: {message.content}')
    print(f'Party ID: {message.party.id}')

Sending Messages

Send to Friend

# Method 1: Using Friend object
friend = client.get_friend('user-id')
await friend.send('Hello!')

# Method 2: Using client.http
await client.http.friend_send_message('user-id', 'Hello!')

Send to Party

# Send message to current party
await client.party.send('Hello everyone!')

Replying to Messages

@client.event
async def event_friend_message(message):
    # Reply to friend message
    await message.reply('Thanks for your message!')

@client.event
async def event_party_message(message):
    # Reply in party chat
    if message.author.id != client.user.id:
        await message.reply(f'You said: {message.content}')

Message Length Limit

Messages are limited to 256 characters. Longer messages will raise an error:
from rebootpy.errors import ChatError

@client.event
async def event_friend_message(message):
    try:
        long_message = 'A' * 300  # Too long!
        await message.reply(long_message)
    except ChatError as e:
        print(f'Message too long: {e}')
        await message.reply('My response was too long!')

Command Patterns

Simple Command Handler

@client.event
async def event_friend_message(message):
    # Ignore messages from self
    if message.author.id == client.user.id:
        return
    
    content = message.content.lower()
    
    if content == '!hello':
        await message.reply('Hello!')
    elif content == '!stats':
        stats = await client.fetch_br_stats(message.author.id)
        await message.reply(f'Wins: {stats.total_wins}')
    elif content == '!help':
        await message.reply('Commands: !hello, !stats, !help')

Command with Arguments

@client.event
async def event_friend_message(message):
    if not message.content.startswith('!'):
        return
    
    parts = message.content.split()
    command = parts[0][1:].lower()  # Remove '!' prefix
    args = parts[1:]
    
    if command == 'user':
        if not args:
            await message.reply('Usage: !user <name>')
            return
        
        username = ' '.join(args)
        user = await client.fetch_user(username)
        
        if user:
            await message.reply(f'Found: {user.display_name} ({user.id})')
        else:
            await message.reply('User not found')
    
    elif command == 'invite':
        await client.party.invite(message.author.id)
        await message.reply('Party invite sent!')

Party Command Handler

@client.event
async def event_party_message(message):
    # Ignore own messages
    if message.author.id == client.user.id:
        return
    
    content = message.content.lower()
    
    if content == '!ready':
        await client.party.me.set_ready(rebootpy.ReadyState.READY)
        await message.reply('Ready!')
    
    elif content == '!privacy public':
        if client.party.me.leader:
            await client.party.set_privacy(rebootpy.PartyPrivacy.PUBLIC)
            await message.reply('Party is now public')
        else:
            await message.reply('I\'m not the leader!')

Conversation Flow

Ask and Wait for Response

import asyncio

@client.event
async def event_friend_message(message):
    if message.content.lower() == '!quiz':
        await message.reply('What is 2 + 2?')
        
        def check(m):
            return m.author.id == message.author.id
        
        try:
            response = await client.wait_for(
                'friend_message',
                check=check,
                timeout=30
            )
            
            if response.content == '4':
                await response.reply('Correct!')
            else:
                await response.reply('Wrong! The answer is 4')
        
        except asyncio.TimeoutError:
            await message.reply('You took too long!')

Multi-step Conversation

@client.event
async def event_friend_message(message):
    if message.content.lower() == '!setup':
        author = message.author
        
        def check(m):
            return m.author.id == author.id
        
        try:
            # Step 1: Ask for name
            await message.reply('What is your name?')
            name_msg = await client.wait_for('friend_message', check=check, timeout=60)
            name = name_msg.content
            
            # Step 2: Ask for age
            await name_msg.reply(f'Nice to meet you, {name}! How old are you?')
            age_msg = await client.wait_for('friend_message', check=check, timeout=60)
            age = age_msg.content
            
            # Done
            await age_msg.reply(f'Setup complete! Name: {name}, Age: {age}')
        
        except asyncio.TimeoutError:
            await message.reply('Setup cancelled (timeout)')

Message Filtering

Ignore Bot Messages

@client.event
async def event_friend_message(message):
    # Don't respond to own messages
    if message.author.id == client.user.id:
        return
    
    await message.reply('I got your message!')

Whitelist System

ALLOWED_USERS = ['user-id-1', 'user-id-2', 'user-id-3']

@client.event
async def event_friend_message(message):
    if message.author.id not in ALLOWED_USERS:
        return  # Ignore messages from non-whitelisted users
    
    # Process message
    await message.reply('Command received!')

Spam Protection

import time
from collections import defaultdict

message_counts = defaultdict(list)
SPAM_THRESHOLD = 5  # messages
SPAM_WINDOW = 10    # seconds

@client.event
async def event_friend_message(message):
    user_id = message.author.id
    current_time = time.time()
    
    # Clean old timestamps
    message_counts[user_id] = [
        t for t in message_counts[user_id]
        if current_time - t < SPAM_WINDOW
    ]
    
    # Check spam
    if len(message_counts[user_id]) >= SPAM_THRESHOLD:
        await message.reply('You\'re sending messages too fast!')
        return
    
    # Add current message timestamp
    message_counts[user_id].append(current_time)
    
    # Process message normally
    await message.reply('Message received')

Auto-responder Patterns

Keyword Auto-response

RESPONSES = {
    'hello': 'Hi there!',
    'help': 'I can help you with commands. Type !commands',
    'thanks': 'You\'re welcome!',
    'bye': 'Goodbye!'
}

@client.event
async def event_friend_message(message):
    content = message.content.lower()
    
    for keyword, response in RESPONSES.items():
        if keyword in content:
            await message.reply(response)
            return

Away Message

AWAY_MODE = True
AWAY_MESSAGE = 'I\'m currently away. I\'ll respond when I\'m back!'

@client.event
async def event_friend_message(message):
    if AWAY_MODE and message.author.id != client.user.id:
        await message.reply(AWAY_MESSAGE)

Auto-forward Messages

FORWARD_TO = 'admin-user-id'

@client.event
async def event_friend_message(message):
    # Forward all messages to admin
    admin = client.get_friend(FORWARD_TO)
    if admin and message.author.id != FORWARD_TO:
        await admin.send(
            f'Message from {message.author.display_name}: {message.content}'
        )

Message Logging

Simple Logger

import datetime

@client.event
async def event_friend_message(message):
    timestamp = message.created_at.strftime('%Y-%m-%d %H:%M:%S')
    log_entry = f'[{timestamp}] {message.author.display_name}: {message.content}'
    
    # Log to file
    with open('messages.log', 'a', encoding='utf-8') as f:
        f.write(log_entry + '\n')
    
    # Also log party messages

@client.event
async def event_party_message(message):
    timestamp = message.created_at.strftime('%Y-%m-%d %H:%M:%S')
    log_entry = f'[{timestamp}] [Party] {message.author.display_name}: {message.content}'
    
    with open('messages.log', 'a', encoding='utf-8') as f:
        f.write(log_entry + '\n')

Database Logging

@client.event
async def event_friend_message(message):
    await save_to_database(
        message_type='friend',
        author_id=message.author.id,
        author_name=message.author.display_name,
        content=message.content,
        timestamp=message.created_at
    )

Party Chat Management

Announce Member Joins

@client.event
async def event_party_member_join(member):
    if member.id != client.user.id:
        await client.party.send(f'Welcome {member.display_name}!')

Party Chat Commands

@client.event
async def event_party_message(message):
    if message.author.id == client.user.id:
        return
    
    content = message.content.lower()
    
    if content == '!members':
        members = ', '.join(m.display_name for m in client.party.members)
        await message.reply(f'Members: {members}')
    
    elif content == '!count':
        count = client.party.member_count
        max_size = client.party.max_size
        await message.reply(f'{count}/{max_size} members')
    
    elif content == '!leader':
        leader = client.party.leader
        await message.reply(f'Leader: {leader.display_name}')

Best Practices

Check message length

Always ensure messages are under 256 characters

Ignore own messages

Filter out message.author.id == client.user.id to avoid loops

Use timeouts

When using wait_for(), always set a timeout

Handle errors gracefully

Catch ChatError and other exceptions

Common Issues

Message Loops

Avoid infinite loops by not replying to own messages:
# Bad - Creates infinite loop
@client.event
async def event_friend_message(message):
    await message.reply('Echo!')  # Bot replies to its own messages!

# Good - Ignores own messages
@client.event
async def event_friend_message(message):
    if message.author.id == client.user.id:
        return
    await message.reply('Echo!')

Message Too Long

Split long messages:
def split_message(text, max_length=256):
    """Split message into chunks"""
    return [text[i:i+max_length] for i in range(0, len(text), max_length)]

@client.event
async def event_friend_message(message):
    response = 'A' * 500  # Very long message
    
    for chunk in split_message(response):
        await message.reply(chunk)

Next Steps

Friends

Learn about friend management

Parties

Understand party chat context

Events

Handle message events

Commands Extension

Use the commands extension for advanced command handling

Build docs developers (and LLMs) love