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 loop

  • send(destination, message, title="Reply", lxmf_fields=None): Send a message to a destination, optionally with custom LXMF fields.

  • send_with_attachment(destination, message, attachment, title="Reply"): Send a message with an attachment

  • command(name, description="No description provided", admin_only=False, threaded=False): Decorator for registering commands. Set threaded=True to run the command’s callback in a separate thread.

  • on_first_message(): Decorator for handling first messages from users

  • 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

Cryptographic message signing and verification for enhanced security:

from lxmfy import SignatureManager

# SignatureManager is automatically available as bot.signature_manager
# when signature_verification_enabled=True

# Manual usage (rarely needed):
sig_manager = SignatureManager(bot, verification_enabled=True, require_signatures=False)

Key Methods

  • sign_message(message, identity): Sign an LXMF message using the provided RNS identity

  • verify_message_signature(message, signature, sender_hash, sender_identity=None): Verify a message signature against a sender identity

  • should_verify_message(sender): Determine if a message from the given sender should be verified

  • handle_unsigned_message(sender, message_hash): Handle messages that lack valid signatures

Signature Fields

LXMFy uses custom LXMF field 0xFA (FIELD_SIGNATURE) to store cryptographic signatures. Messages are canonicalized by sorting and concatenating fields in the following order:

  • source hash (prefixed with “source:”)

  • destination hash (prefixed with “dest:”)

  • content (prefixed with “content:”)

  • title (prefixed with “title:”)

  • timestamp (prefixed with “timestamp:”)

  • custom fields (excluding signature field, prefixed with “field_{id}:”)

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)}")