LXMF bot framework https://lxmfy.quad4.io
Find a file
2025-11-22 10:20:34 -06:00
.github/workflows Update Dockerfile paths in CI workflows to reflect new directory structure 2025-11-03 11:58:12 -06:00
docker Update Docker setup to use Poetry for dependency management 2025-11-19 22:52:29 -06:00
lxmfy Fix formatting in debug log 2025-11-22 10:20:26 -06:00
tests Add propagation test and format other tests 2025-11-22 10:20:15 -06:00
.deepsource.toml Update DeepSource configuration to exclude test files from analysis 2025-09-27 03:37:52 -05:00
.dockerignore add 2025-07-14 12:53:49 -05:00
.gitignore Update 2025-09-27 03:35:11 -05:00
CHANGELOG.md 1.1.0 2025-11-21 15:59:51 -06:00
LICENSE License update 2025-04-29 02:25:03 -05:00
Makefile Remove wheel, sdist, and dist targets from Makefile to simplify build process. 2025-11-19 22:52:34 -06:00
poetry.lock Bump lxmf and rns versions to 0.9.3 and 1.0.3 respectively in poetry.lock, pyproject.toml, requirements.txt, and uv.lock 2025-11-19 22:41:02 -06:00
pyproject.toml Update pyproject.toml with author email, license, keywords, and classifiers; add project URLs for homepage and repository. 2025-11-19 22:52:44 -06:00
README.md Update README 2025-11-22 10:20:34 -06:00
SECURITY.md Update 2025-07-14 01:56:29 -05:00

LXMFy

Socket Badge DeepSource Build Test Publish Python distribution to PyPI Safety Test

Easily create LXMF bots for the Reticulum Network with this extensible framework.

Docs

Features

  • Interactive CLI
  • Spam protection (rate limiting, command cooldown, warnings, banning)
  • Command prefix (set to None to process all messages as commands)
  • Announcements (announce in seconds, set to 0 to disable)
  • Extensible Storage Backend (JSON, SQLite)
  • Permission System (Role-based)
  • Middleware System
  • Task Scheduler (Cron-style)
  • Event System
  • Help on first message
  • LXMF Attachments (File, Image, Audio)
  • Customizable Bot Icon (via LXMF Icon Appearance field)
  • Direct Delivery & Propagation Fallback
  • Threading support for commands.
  • Cryptographic Message Signing & Verification (LXMF)

Installation

pip install lxmfy

or pipx:

pipx install lxmfy

or uv:

uv sync

or via git

pipx install git+https://github.com/lxmfy/LXMFy.git

or temporary environment with uv:

uvx --from git+https://github.com/lxmfy/LXMFy.git lxmfy

Usage

lxmfy

or with uv:

uv run lxmfy

Create bots:

lxmfy create

Docker

Building Manually

To build the Docker image, navigate to the root of the project and run:

docker build -t lxmfy-test .

Once built, you can run the Docker image:

docker run -d \
    --name lxmfy-test-bot \
    -v $(pwd)/config:/bot/config \
    -v $(pwd)/.reticulum:/root/.reticulum \
    --restart unless-stopped \
    lxmfy-test

Auto-Interface support (network host):

docker run -d \
    --name lxmfy-test-bot \
    --network host \
    -v $(pwd)/config:/bot/config \
    -v $(pwd)/.reticulum:/root/.reticulum \
    --restart unless-stopped \
    lxmfy-test

Building Wheels with docker/Dockerfile.Build

The docker/Dockerfile.Build is used to build the lxmfy Python package into a wheel file within a Docker image.

docker build -f docker/Dockerfile.Build -t lxmfy-wheel-builder .

This will create an image named lxmfy-wheel-builder. To extract the built wheel file from the image, you can run a container from this image and copy the dist directory:

docker run --rm -v "$(pwd)/dist_output:/output" lxmfy-wheel-builder

This command will create a dist_output directory in your current working directory and copy the built wheel file into it.

Example

from lxmfy import LXMFBot, load_cogs_from_directory

bot = LXMFBot(
    name="LXMFy Test Bot", # Name of the bot that appears on the network.
    announce=5400, # Announce every hour, set to 0 to disable.
    announce_enabled=True, # Set to False to disable all announces (both initial and periodic)
    announce_immediately=True, # Set to False to disable initial announce
    admins=["your_lxmf_hash_here"], # List of admin hashes.
    hot_reloading=True, # Enable hot reloading.
    command_prefix="/", # Set to None to process all messages as commands.
    cogs_dir="cogs", # Specify cogs directory name.
    rate_limit=5, # 5 messages per minute
    cooldown=5, # 5 seconds cooldown
    max_warnings=3, # 3 warnings before ban
    warning_timeout=300, # Warnings reset after 5 minutes
    signature_verification_enabled=True, # Enable cryptographic signature verification
    require_message_signatures=False, # Allow unsigned messages but log them
    propagation_fallback_enabled=True, # Enable propagation fallback after direct delivery fails
    propagation_node="your_propagation_node_hash_here", # Manual propagation node (optional)
    autopeer_propagation=True, # Auto-discover propagation nodes (optional)
    autopeer_maxdepth=4, # Max hops for auto-peering (default: 4)
    enable_propagation_node=False, # Run as propagation node (default: False)
    message_storage_limit_mb=500, # Storage limit in MB for propagation node (default: 500)
    direct_delivery_retries=3, # Number of direct delivery attempts before falling back to propagation
)

# Dynamically load all cogs
load_cogs_from_directory(bot)

@bot.command(name="ping", description="Test if bot is responsive")
def ping(ctx):
    ctx.reply("Pong!")

# Admin Only Command
@bot.command(name="echo", description="Echo a message", admin_only=True)
def echo(ctx, message: str):
    ctx.reply(message)

bot.run()

Cryptographic Message Signing

LXMFy supports cryptographic signing and verification of messages for enhanced security:

bot = LXMFBot(
    name="SecureBot",
    signature_verification_enabled=True,  # Enable signature verification
    require_message_signatures=False,     # Allow unsigned messages but log them
    # ... other config
)

CLI Commands for Signatures

# Test signature functionality
lxmfy signatures test

# Get enable instructions
lxmfy signatures enable

# Get disable instructions
lxmfy signatures disable

Propagation Node Configuration

LXMFy supports three modes for propagation node usage:

1. Manual Configuration

Set a specific propagation node by hash:

bot = LXMFBot(
    name="MyBot",
    propagation_fallback_enabled=True,
    propagation_node="your_propagation_node_hash_here",  # Manual node configuration
    direct_delivery_retries=3,
)

2. Automatic Discovery (Auto-Peering)

Let the bot automatically discover and use propagation nodes from network announces:

bot = LXMFBot(
    name="MyBot",
    propagation_fallback_enabled=True,
    autopeer_propagation=True,  # Enable automatic discovery
    autopeer_maxdepth=4,  # Maximum hop distance for auto-peering (default: 4)
)

The bot will listen for propagation node announces and automatically peer with suitable nodes within the configured hop depth.

3. Run as Propagation Node

Your bot can act as a propagation node itself to store and forward messages:

bot = LXMFBot(
    name="MyPropagationBot",
    enable_propagation_node=True,  # Enable propagation node mode
    message_storage_limit_mb=500,  # Limit storage to 500 MB (default)
)

When running as a propagation node, the bot will store messages for offline users and forward them when the recipients come online. The message_storage_limit_mb prevents the bot from consuming unlimited disk space. Set to 0 for unlimited storage (not recommended).

Querying Propagation Status

You can check the current propagation configuration and discovered nodes:

status = bot.get_propagation_node_status()
print(f"Current outbound node: {status['current_outbound_node']}")
print(f"Discovered peers: {status['discovered_peers']}")

Dynamically Setting Propagation Node

You can change the propagation node at runtime:

bot.set_propagation_node("new_propagation_node_hash")

Managing Storage Limits

When running as a propagation node, you can query and adjust storage limits:

# Get current storage statistics
stats = bot.get_propagation_storage_stats()
print(f"Storage used: {stats['storage_size_mb']:.2f} MB")
print(f"Storage limit: {stats['storage_limit_mb']} MB")
print(f"Utilization: {stats['utilization_percent']:.1f}%")
print(f"Messages stored: {stats['message_count']}")

# Change storage limit at runtime
bot.set_message_storage_limit(megabytes=1000)  # Set to 1 GB

Important Notes

  • Without configuring propagation (manual, auto-peer, or running as a node), messages requiring propagation will fail
  • You can combine modes: e.g., set a manual node AND enable auto-peering as backup
  • When running as a propagation node, your bot can still send and receive messages normally
  • Auto-peering respects the autopeer_maxdepth setting to avoid connecting to distant nodes

Development

  • poetry or uv
  • python 3.11 or higher

With poetry:

poetry install
poetry run lxmfy run echo

With uv:

uv sync
uv run lxmfy run echo

Contributing

Pull requests are welcome.

Part of Quad4

LXMFy is a Quad4 project.

License

MIT