Core Components ================ LXMFBot -------- The main bot class that handles message routing, command processing, and bot lifecycle management. .. code-block:: python 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 ^^^^^^^^^^^ - :code:`run(delay=10)`: Start the bot's main loop - :code:`send(destination, message, title="Reply", lxmf_fields=None)`: Send a message to a destination, optionally with custom LXMF fields. - :code:`send_with_attachment(destination, message, attachment, title="Reply")`: Send a message with an attachment - :code:`command(name, description="No description provided", admin_only=False, threaded=False)`: Decorator for registering commands. Set :code:`threaded=True` to run the command's callback in a separate thread. - :code:`on_first_message()`: Decorator for handling first messages from users - :code:`validate()`: Run validation checks on the bot configuration Storage ------- The framework provides two storage backends: JSONStorage ^^^^^^^^^^^ .. code-block:: python from lxmfy import JSONStorage storage = JSONStorage("data") SQLiteStorage ^^^^^^^^^^^^^ .. code-block:: python from lxmfy import SQLiteStorage storage = SQLiteStorage("data/bot.db") Commands -------- Command registration and handling: .. code-block:: python @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. .. code-block:: python 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 :code:`threaded=True` **must not** directly interact with the Reticulum Network Stack (RNS) or any components that rely on :code:`lxmfy.transport.py`, as these are generally not thread-safe. Use :code:`ctx.reply()` for sending messages back to the user from within a threaded command. Events ------ Event system for handling various bot events: .. code-block:: python @bot.events.on("message_received", EventPriority.HIGHEST) def handle_message(event): # Handle message event pass Permissions ----------- Permission system for controlling access to bot features: .. code-block:: python 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: .. code-block:: python @bot.middleware.register(MiddlewareType.PRE_COMMAND) def pre_command_middleware(ctx): # Process before command execution pass Attachments ----------- Support for sending files, images, and audio: .. code-block:: python 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 :code:`LXMF.FIELD_ICON_APPEARANCE`. .. code-block:: python 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: .. code-block:: python @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: .. code-block:: python 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 ^^^^^^^^^^^ - :code:`sign_message(message, identity)`: Sign an LXMF message using the provided RNS identity - :code:`verify_message_signature(message, signature, sender_hash, sender_identity=None)`: Verify a message signature against a sender identity - :code:`should_verify_message(sender)`: Determine if a message from the given sender should be verified - :code:`handle_unsigned_message(sender, message_hash)`: Handle messages that lack valid signatures Signature Fields ^^^^^^^^^^^^^^^^ LXMFy uses custom LXMF field :code:`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: .. code-block:: python from lxmfy.templates import EchoBot bot = EchoBot() bot.run() MemeBot ------- Bot for sending random memes: .. code-block:: python from lxmfy.templates import MemeBot bot = MemeBot() bot.run() NoteBot ------- Note-taking bot with JSON storage: .. code-block:: python from lxmfy.templates import NoteBot bot = NoteBot() bot.run() ReminderBot ----------- Reminder bot with SQLite storage: .. code-block:: python from lxmfy.templates import ReminderBot bot = ReminderBot() bot.run() CLI Tools ========= The framework provides command-line tools for bot management: .. code-block:: bash # 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: .. code-block:: python try: bot.run() except KeyboardInterrupt: bot.cleanup() except Exception as e: logger.error(f"Error running bot: {str(e)}")