Core Components¶
LXMFBot¶
The main bot class that handles message routing, command processing, and bot lifecycle management.
from lxmfy import LXMFBot
bot = LXMFBot(
name="MyBot",
announce=600,
announce_immediately=True,
admins=set(),
hot_reloading=False,
rate_limit=5,
cooldown=60,
max_warnings=3,
warning_timeout=300,
command_prefix="/",
cogs_dir="cogs",
cogs_enabled=True,
permissions_enabled=False,
storage_type="json",
storage_path="data",
first_message_enabled=True,
event_logging_enabled=True,
max_logged_events=1000,
event_middleware_enabled=True,
announce_enabled=True,
signature_verification_enabled=False,
require_message_signatures=False
)
Key Methods¶
run(delay=10): Start the bot’s main loopsend(destination, message, title="Reply", lxmf_fields=None, propagation_node=None, max_retries=3): Send a message to a destination, optionally with custom LXMF fields, specific propagation node, and retry configuration.send_with_attachment(destination, message, attachment, title="Reply"): Send a message with an attachmentcommand(name, description="No description provided", admin_only=False, threaded=False): Decorator for registering commands. Setthreaded=Trueto run the command’s callback in a separate thread.on_first_message(): Decorator for handling first messages from userson_message(): Decorator for handling all messages (called before command processing)validate(): Run validation checks on the bot configuration
Storage¶
The framework provides two storage backends:
JSONStorage¶
from lxmfy import JSONStorage
storage = JSONStorage("data")
SQLiteStorage¶
from lxmfy import SQLiteStorage
storage = SQLiteStorage("data/bot.db")
Commands¶
Command registration and handling:
@bot.command(name="hello", description="Says hello")
def hello(ctx):
ctx.reply(f"Hello {ctx.sender}!")
Threaded Commands¶
For long-running or blocking operations that do not interact with the Reticulum Network Stack directly, you can run commands in a separate thread to keep the bot responsive.
import time
@bot.command(name="long_task", description="Performs a long-running task in a separate thread", threaded=True)
def long_task_command(ctx):
ctx.reply("Starting a long task... please wait.")
time.sleep(10) # This runs in a separate thread
ctx.reply("Long task completed!")
Important: Functions marked as threaded=True must not directly interact with the Reticulum Network Stack (RNS) or any components that rely on lxmfy.transport.py, as these are generally not thread-safe. Use ctx.reply() for sending messages back to the user from within a threaded command.
Events¶
Event system for handling various bot events:
@bot.events.on("message_received", EventPriority.HIGHEST)
def handle_message(event):
# Handle message event
pass
Permissions¶
Permission system for controlling access to bot features:
from lxmfy import DefaultPerms
@bot.command(name="admin", description="Admin command", admin_only=True)
def admin_command(ctx):
if ctx.is_admin:
ctx.reply("Admin command executed")
Middleware¶
Middleware system for processing messages and events:
@bot.middleware.register(MiddlewareType.PRE_COMMAND)
def pre_command_middleware(ctx):
# Process before command execution
pass
Attachments¶
Support for sending files, images, and audio:
from lxmfy import Attachment, AttachmentType
attachment = Attachment(
type=AttachmentType.IMAGE,
name="image.jpg",
data=image_data,
format="jpg"
)
bot.send_with_attachment(destination, "Here's an image", attachment)
Icon Appearance (LXMF Field)¶
You can set a custom icon for your bot that compliant LXMF clients can display. This uses the LXMF.FIELD_ICON_APPEARANCE.
from lxmfy import IconAppearance, pack_icon_appearance_field
import LXMF # Required for LXMF.FIELD_ICON_APPEARANCE
# Define the icon appearance
icon_data = IconAppearance(
icon_name="smart_toy", # Name from Material Symbols
fg_color=b'\xFF\xFF\xFF', # White foreground (3 bytes)
bg_color=b'\x4A\x90\xE2' # Blue background (3 bytes)
)
# Pack it into the LXMF field format
icon_lxmf_field = pack_icon_appearance_field(icon_data)
# Send a message with this icon
bot.send(
destination_hash_str,
"Hello from your friendly bot!",
title="Bot Message",
lxmf_fields=icon_lxmf_field
)
# You can also combine it with other fields, like attachments:
# attachment_field = pack_attachment(some_attachment)
# combined_fields = {**icon_lxmf_field, **attachment_field}
# bot.send(destination, "Message with icon and attachment", lxmf_fields=combined_fields)
Scheduler¶
Task scheduling system:
@bot.scheduler.schedule(name="daily_task", cron_expr="0 0 * * *")
def daily_task():
# Run daily at midnight
pass
Signatures¶
LXMFy provides configuration options for LXMF’s built-in cryptographic message signing and verification:
from lxmfy import LXMFBot
bot = LXMFBot(
name="SecureBot",
signature_verification_enabled=True, # Enable signature checks
require_message_signatures=False # Set to True to reject unsigned messages
)
Important: LXMF automatically handles all cryptographic signing and verification using RNS identities. LXMFy’s SignatureManager is a configuration layer that:
Controls whether to enforce signature verification
Determines policy for unsigned messages (accept or reject)
Integrates with the permission system (e.g., bypass verification for trusted users)
The actual cryptographic operations are performed by LXMF/RNS, not by LXMFy.
SignatureManager Methods¶
The SignatureManager is available as bot.signature_manager when signature_verification_enabled=True:
should_verify_message(sender): Determine if a message from the given sender should be verifiedhandle_unsigned_message(sender, message_hash): Handle messages that lack valid signatures based on policy
How LXMF Signatures Work¶
LXMF automatically signs all outgoing messages using the sender’s RNS identity during the pack() operation. When messages are received, LXMF validates signatures and provides:
message.signature_validated: Boolean indicating if the signature is validmessage.unverified_reason: Reason code if validation failed (e.g.,SIGNATURE_INVALID,SOURCE_UNKNOWN)
LXMFy uses these built-in LXMF properties to enforce your bot’s signature policy.
Message Delivery¶
LXMFy provides advanced message delivery features including propagation nodes and automatic retries:
Propagation Nodes¶
Send messages through specific propagation nodes for improved reliability on the Reticulum network:
# Send via a specific propagation node
bot.send(
destination_hash,
"Message content",
propagation_node="<propagation_node_hash>"
)
# The propagation node hash should be a valid LXMF propagation node
# on the Reticulum network
Automatic Retries¶
Configure automatic retry attempts for failed message deliveries:
# Send with custom retry count
bot.send(
destination_hash,
"Important message",
max_retries=5 # Will retry up to 5 times on delivery failure
)
# Default max_retries is 3
# Retry logic automatically handles delivery callbacks
The retry system tracks delivery attempts per destination and automatically retries failed deliveries. Successful deliveries reset the retry counter for that destination.
Message Handlers¶
LXMFy provides decorators for handling different types of incoming messages:
First Message Handler¶
Handle the first message from each user:
@bot.on_first_message()
def welcome_user(sender, message):
content = message.content.decode("utf-8")
bot.send(sender, f"Welcome! You said: {content}")
return True # Return True to stop further processing
General Message Handler¶
Handle all incoming messages before command processing:
@bot.on_message()
def handle_all_messages(sender, message):
content = message.content.decode("utf-8").strip()
# Custom logic here
if content.startswith("echo:"):
bot.send(sender, content[5:])
return True # Stop further processing
return False # Continue to command processing
Message handlers are called in this order:
1. First message handler (if this is the first message from this sender)
2. General message handlers (registered with on_message())
3. Command processing (if message starts with command prefix)
Templates¶
The framework includes several ready-to-use bot templates:
EchoBot¶
Simple echo bot that repeats messages:
from lxmfy.templates import EchoBot
bot = EchoBot()
bot.run()
MemeBot¶
Bot for sending random memes:
from lxmfy.templates import MemeBot
bot = MemeBot()
bot.run()
NoteBot¶
Note-taking bot with JSON storage:
from lxmfy.templates import NoteBot
bot = NoteBot()
bot.run()
ReminderBot¶
Reminder bot with SQLite storage:
from lxmfy.templates import ReminderBot
bot = ReminderBot()
bot.run()
CLI Tools¶
The framework provides command-line tools for bot management:
# Create a new bot
lxmfy create mybot
# Create a bot from template
lxmfy create --template echo mybot
# Run a template bot
lxmfy run echo
# Analyze bot configuration
lxmfy analyze bot.py
# Verify package signature
lxmfy verify package.whl sigstore.json
# Test signature verification with a message
lxmfy signatures test
# Enable signature verification
lxmfy signatures enable
# Disable signature verification
lxmfy signatures disable
Error Handling¶
The framework provides comprehensive error handling:
try:
bot.run()
except KeyboardInterrupt:
bot.cleanup()
except Exception as e:
logger.error(f"Error running bot: {str(e)}")