Создание ботов¶
Базовая структура¶
Минимальный бот LXMFy включает в себя:
Импорт
LXMFBot.Создание экземпляра
LXMFBotс желаемой конфигурацией.Определение команд или обработчиков событий.
Запуск бота с помощью
bot.run().
from lxmfy import LXMFBot
# 1. Instantiate the bot
bot = LXMFBot(
name="SimpleBot",
command_prefix="!",
storage_path="simple_data"
)
# 2. Define commands
@bot.command(name="ping", description="Responds with pong")
def ping_command(ctx):
# ctx is a context object containing message info
# ctx.sender: Sender's LXMF hash
# ctx.content: Full message content
# ctx.args: List of arguments after the command
# ctx.reply(message): Function to send a reply
# (can also take keyword arguments like title="My Title", lxmf_fields=some_fields)
ctx.reply("Pong!")
# For long-running tasks, you can use threaded commands:
# import time
# @bot.command(name="long_op", description="Performs a long operation in a separate thread", threaded=True)
# def long_op_command(ctx):
# ctx.reply("Starting long operation...")
# time.sleep(10) # Simulate a long-running operation
# ctx.reply("Long operation complete!")
# Important: Threaded commands should not directly interact with RNS or lxmfy.transport.py.
@bot.command(name="greet", description="Greets the user")
def greet_command(ctx):
if ctx.args:
name = " ".join(ctx.args)
ctx.reply(f"Hello, {name}!")
else:
ctx.reply("Hello there! Tell me your name: !greet <your_name>")
# 3. Run the bot
if __name__ == "__main__":
print(f"Starting bot: {bot.config.name}")
print(f"Bot LXMF Address: {bot.local.hash}")
bot.run()
Использование шаблонов¶
LXMFy предоставляет несколько шаблонов для распространенных типов ботов. Вы можете использовать CLI для создания файла бота на основе шаблона.
# Create an echo bot
lxmfy create --template echo my_echo_bot
# Create a reminder bot (uses SQLite storage)
lxmfy create --template reminder my_reminder_bot
# Create a note-taking bot (uses JSON storage)
lxmfy create --template note my_note_bot
# Create a cog test bot (tests cog loading features)
lxmfy create --template cogtest my_cog_test_bot
Выполнение этих команд создает файл Python (например, my_echo_bot.py), который импортирует и запускает выбранный шаблон. Затем вы можете изменить сгенерированный файл или сам код шаблона (lxmfy/templates/...).
Example generated file (:code:`my_cog_test_bot.py`):
from lxmfy.templates import CogTestBot
if __name__ == "__main__":
bot = CogTestBot() # Creates an instance of the CogTestBot template
# You can optionally override the default name:
# bot.bot.name = "My Cog Test Bot"
bot.run()
Конфигурация бота¶
При создании экземпляра LXMFBot вы можете передать различные именованные аргументы для настройки его поведения. Список распространенных опций см. в разделе BotConfig в Справочнике API или в Руководстве по быстрому запуску.
from lxmfy import LXMFBot
bot = LXMFBot(
name="ConfiguredBot",
announce=3600, # Announce every hour
admins={"your_admin_hash_here"}, # Set admin user(s)
command_prefix="$", # Use '$' as prefix
storage_type="sqlite", # Use SQLite database
storage_path="data/my_bot_data.db", # Specify DB file path
rate_limit=10, # Allow 10 messages / minute
cooldown=30, # Cooldown of 30 seconds
permissions_enabled=True # Enable role-based permissions
)
if __name__ == "__main__":
# You can also modify config after instantiation
# Note: some settings are best set during init
bot.config.max_warnings = 5
bot.spam_protection.config.max_warnings = 5 # Update spam protector too
bot.run()
Установка иконки бота (поле LXMF)¶
Вы можете присвоить своему боту пользовательскую иконку, которая будет отображаться в совместимых клиентах LXMF. Для этого используется LXMF.FIELD_ICON_APPEARANCE, и ее можно установить при отправке сообщений.
Сначала убедитесь, что у вас есть необходимые импорты:
from lxmfy import IconAppearance, pack_icon_appearance_field
Затем вы можете определить и использовать иконку:
# In your bot class or setup
icon_data = IconAppearance(
icon_name="robot_2", # Choose from Material Symbols
fg_color=b'\x00\xFF\x00', # Green
bg_color=b'\x33\x33\x33' # Dark Grey
)
self.bot_icon_field = pack_icon_appearance_field(icon_data)
# When sending a message or replying:
ctx.reply("Message from your bot!", lxmf_fields=self.bot_icon_field)
# or
# bot.send(destination, "Another message", lxmf_fields=self.bot_icon_field)
Это поле self.bot_icon_field можно предварительно рассчитать и использовать повторно для всех сообщений, отправляемых ботом.
Использование модулей (расширений)¶
Модули позволяют вам организовывать команды и прослушиватели событий в отдельные файлы (модули), сохраняя основной файл вашего бота в чистоте.
Создайте каталог :code:`cogs` (или любое другое имя, которое вы указали для
cogs_dirвBotConfig).Создайте файлы Python внутри каталога
cogs(например,utility.py).Определите класс, который наследуется от
lxmfy.Cog(необязательно, но рекомендуется) или является просто стандартным классом.Определите команды как методы внутри класса с помощью декоратора
@Command.Создайте функцию :code:`setup(bot)` в файле модуля, которую LXMFy вызовет для регистрации модуля.
Пример (:code:`cogs/utility.py`):
from lxmfy import Command
from lxmfy.commands import Cog # Import Cog if inheriting
import time
class UtilityCog: # Or class UtilityCog(Cog):
def __init__(self, bot):
self.bot = bot
self.start_time = time.time()
@Command(name="uptime", description="Shows bot uptime")
# Note: Methods in cogs often take 'self' and 'ctx'
def uptime_command(self, ctx):
uptime_seconds = time.time() - self.start_time
ctx.reply(f"Bot has been running for {uptime_seconds:.2f} seconds.")
@Command(name="info", description="Shows bot info")
def info_command(self, ctx):
info = (
f"Bot Name: {self.bot.config.name}\n"
f"Owner(s): {', '.join(self.bot.config.admins) or 'None'}\n"
f"Prefix: {self.bot.config.command_prefix}"
)
ctx.reply(info)
@Command(name="threaded_cog_task", description="Performs a long task in a cog thread", threaded=True)
def threaded_cog_task(self, ctx):
ctx.reply("Starting a long cog task... this will run in a separate thread.")
time.sleep(7) # Simulate a long-running operation
ctx.reply("Long cog task completed!")
# This function is required for the cog to be loaded
def setup(bot):
cog_instance = UtilityCog(bot)
bot.add_cog(cog_instance) # Register the cog instance with the bot
Основной файл бота (:code:`my_bot.py`):
from lxmfy import LXMFBot
bot = LXMFBot(
name="CogBot",
cogs_enabled=True, # Make sure cogs are enabled (default)
cogs_dir="cogs" # Point to the directory
)
if __name__ == "__main__":
# Cogs are loaded automatically during LXMFBot initialization
# if cogs_enabled is True.
bot.run()
Когда бот запустится, он автоматически найдет utility.py, вызовет его функцию setup, которая создаст экземпляр UtilityCog и зарегистрирует его с помощью bot.add_cog(). После этого станут доступны команды, определенные в модуле (uptime, info).
External Script Cogs (Multi-Language Support)¶
You can also write bot extensions in languages other than Python (e.g., Bash, Ruby, Perl, Go, C) using External Script Cogs.
Create an executable script in your
cogsdirectory.Add a shebang at the top of the script (e.g.,
#!/bin/bash).Ensure the script is executable (
chmod +x your_script).
When the bot starts, it will automatically register any executable file in the cogs directory (that doesn’t end in .py) as a bot command.
Argument Protocol:
$1: Sender’s LXMF hash.$2: Full message content.$3,$4, …: Individual command arguments.
Environment Variables:
LXMFY_SENDER: The sender’s identity hash.LXMFY_CONTENT: The full message content.LXMFY_HAS_ADMIN:trueorfalsedepending on the sender’s admin status.
Example Bash Cog (:code:`cogs/greet.sh`):
#!/bin/bash
echo "Hello from Bash! You sent: $2"
When a user sends /greet hello, the bot will execute this script and reply with its stdout: Hello from Bash! You sent: /greet hello.
Sovereign NLP (Local Intent Classification)¶
LXMFy includes a built-in, lightweight NLP engine for intent classification. This allows your bot to understand the «intent» of a message even if it doesn’t match a command exactly.
Enable NLP in your bot configuration:
nlp_enabled=True.Define intents using the
@bot.intentdecorator.
@bot.intent("help", examples=["how do I use this?", "show me commands", "help me please"])
def help_intent(msg):
msg.reply("I can help! Try typing /help to see a list of commands.")
The NLP engine uses mathematical vector similarity (TF-IDF and Cosine Similarity) to match incoming text against your example phrases. This processing happens entirely locally on your machine, ensuring full privacy.
Persistence and Extensibility:
For larger bots, you can export and import the trained intent model to avoid retraining on every startup:
# Export the model
model_data = bot.nlp.export_model()
# Save model_data to a file or database
# Later, import it back
bot.nlp.import_model(model_data)
RNS Link Support¶
Bots can now establish and respond to direct RNS Links. This is useful for stateful, streaming, or high-bandwidth communication that goes beyond simple message packets.
Enable Link Support in configuration:
link_support_enabled=True.Request a link:
bot.request_link(destination_hash). You can also specify a custom app name and aspects:bot.request_link(dest, callback, "my_app", "aspect1").Handle incoming links: Register a callback with
bot.on_link(handler).
def handle_link(link):
print(f"Link established with {RNS.hexrep(link.destination.hash)}")
# You can now use the link for direct RNS communication
bot.on_link(handle_link)
Safety & Sandboxing:
Timeouts: External cogs have a default timeout (30s) to prevent hanging. This is configurable via
external_cogs_timeout.Threading: All external cogs run in separate threads and do not block the bot.
Sandboxing (Linux only): If
bubblewrap(bwrap) orfirejailis installed, the bot can automatically run scripts in a restricted, read-only sandbox. This is enabled by default viaexternal_cogs_sandbox_enabled.
Handling Messages¶
LXMFy предоставляет несколько способов обработки входящих сообщений на разных этапах.
Обработчик первого сообщения¶
Обработка первого сообщения от каждого нового пользователя (полезно для приветственных сообщений):
from lxmfy import LXMFBot
bot = LXMFBot(
name="WelcomeBot",
first_message_enabled=True # Must be True (default)
)
@bot.on_first_message()
def welcome_new_user(sender, message):
content = message.content.decode("utf-8")
bot.send(
sender,
f"Welcome to the bot! You said: {content}\n\n"
"Type /help to see available commands."
)
return True # Return True to stop further processing of this message
if __name__ == "__main__":
bot.run()
Общий обработчик сообщений¶
Обработка всех входящих сообщений перед обработкой команд:
from lxmfy import LXMFBot
bot = LXMFBot(name="EchoBot")
@bot.on_message()
def echo_non_commands(sender, message):
content = message.content.decode("utf-8").strip()
# Check if this is a command - if so, let command handler deal with it
if content.startswith(bot.config.command_prefix):
command_name = content.split()[0][len(bot.config.command_prefix):]
if command_name in bot.commands:
return False # Let command handler process it
# Not a command, echo it back
bot.send(sender, f"You said: {content}")
return False # Return False to continue processing (though no commands will match)
@bot.command(name="hello", description="Say hello")
def hello_command(ctx):
ctx.reply("Hello! This is a command response.")
if __name__ == "__main__":
bot.run()
Порядок обработки обработчиков сообщений:
Обработчик первого сообщения (если
first_message_enabled=Trueи это первое сообщение от отправителя)Общие обработчики сообщений (зарегистрированные с помощью
@bot.on_message())Обработка команд (если сообщение соответствует зарегистрированной команде)
Обработчики могут возвращать True для прекращения дальнейшей обработки или False для перехода к следующему этапу.
Обработка событий¶
Вы можете регистрировать обработчики для различных событий бота с помощью декоратора @bot.events.on().
from lxmfy import LXMFBot
from lxmfy.events import EventPriority # Optional for priority
bot = LXMFBot(name="EventBot")
@bot.events.on("message_received")
def log_message(event):
# Event object contains details
sender = event.data.get("sender")
message_content = event.data.get("message").content.decode('utf-8', errors='ignore')
print(f"Received message from {sender}: {message_content}")
# You can cancel event processing (e.g., stop message handling)
# if sender == "some_blocked_hash":
# event.cancel()
@bot.events.on("command_executed", priority=EventPriority.LOW)
def log_command(event):
# Example: event.data might contain {'command_name': 'ping', 'sender': '...', ...}
command_name = event.data.get('command_name', 'unknown')
sender = event.data.get('sender', 'unknown')
print(f"Command '{command_name}' executed by {sender}")
# You can define custom events too
@bot.command(name="special")
def special_command(ctx):
ctx.reply("Doing something special!")
# Dispatch a custom event
bot.events.dispatch(Event("special_action_taken", data={"user": ctx.sender}))
@bot.events.on("special_action_taken")
def handle_special(event):
user = event.data.get("user")
print(f"Special action was taken by user: {user}")
if __name__ == "__main__":
bot.run()
См. lxmfy/events.py для получения дополнительной информации о структуре и приоритетах Event.
Хранилище¶
LXMFy provides JSON, SQLite, and In-Memory storage backends.
JSON: Простой, человекочитаемый формат. Подходит для небольших наборов данных. Настраивается с помощью
storage_type="json"иstorage_path="your_data_dir".SQLite: Более эффективен для больших наборов данных или частых записей. Настраивается с помощью
storage_type="sqlite"иstorage_path="your_db_file.db".Memory: Entirely in-RAM storage. State is lost on shutdown. Configure with
storage_type="memory".
Вы можете получить доступ к интерфейсу хранилища через bot.storage:
# Save data
bot.storage.set("user_prefs:" + ctx.sender, {"theme": "dark"})
# Get data (with a default value)
prefs = bot.storage.get("user_prefs:" + ctx.sender, {})
theme = prefs.get("theme", "light")
# Check if data exists
if bot.storage.exists("some_key"):
print("Key exists!")
# Delete data
bot.storage.delete("old_data_key")
# Scan for keys with a prefix (useful for listing user data)
user_keys = bot.storage.scan("user_prefs:")
for key in user_keys:
user_data = bot.storage.get(key)
print(f"Data for {key}: {user_data}")
См. lxmfy/storage.py и справочник по API для получения дополнительной информации.
Разрешения¶
LXMFy включает дополнительную систему разрешений на основе ролей. Включите ее с помощью permissions_enabled=True во время инициализации LXMFBot.
Роли: Определите роли с определенными разрешениями (например,
DefaultPerms.MANAGE_USERS).Разрешения: Детальные флаги, определенные в
DefaultPerms(например,USE_COMMANDS,BYPASS_SPAM).Назначение: Назначьте роли хэшам пользователей.
Подробности использования см. в lxmfy/permissions.py, справочнике по API и, возможно, в примерах модулей (если они есть).
Проверка подписи¶
LXMFy provides configuration for LXMF’s built-in cryptographic message signing and verification. All LXMF messages are automatically signed by the LXMF/RNS stack - LXMFy simply allows you to enforce signature verification policies.
Configuration:
Включите проверку подписи в конфигурации вашего бота:
bot = LXMFBot(
name="SecureBot",
signature_verification_enabled=True, # Enable signature checking
require_message_signatures=False # Set to True to reject unsigned messages
)
Как это работает:
LXMF automatically handles all cryptographic operations:
Outgoing Messages: LXMF automatically signs all messages using the sender’s RNS identity during message packing.
Incoming Messages: LXMF automatically validates signatures using the sender’s RNS identity and provides validation results.
Роль LXMFy: LXMFy проверяет результаты проверки LXMF и применяет вашу политику:
Если
signature_verification_enabled=False: все сообщения принимаются (по умолчанию)Если
signature_verification_enabled=Trueиrequire_message_signatures=False: сообщения принимаются, но неподписанные/недействительные подписи регистрируютсяЕсли
signature_verification_enabled=Trueиrequire_message_signatures=True: неподписанные или недействительные сообщения отклоняются
Permission Integration: Users with
BYPASS_SPAMpermission can bypass signature verification requirements.
Управление через CLI:
Вы можете управлять настройками проверки подписи с помощью CLI:
# Test signature verification
lxmfy signatures test
# Enable signature verification
lxmfy signatures enable
# Disable signature verification
lxmfy signatures disable
Технические детали:
LXMF использует подписи Ed25519, предоставляемые криптографической системой RNS. Каждое сообщение LXMF включает подпись отправителя, которая проверяется по его известному идентификатору RNS. LXMFy просто считывает свойства LXMF message.signature_validated и message.unverified_reason для применения политики безопасности вашего бота.
Расширенная доставка сообщений¶
LXMFy поддерживает расширенные параметры доставки сообщений для повышения надежности.
Использование узлов распространения¶
Отправляйте сообщения через определенные узлы распространения LXMF:
from lxmfy import LXMFBot
bot = LXMFBot(name="PropagationBot")
@bot.command(name="send", description="Send via propagation node")
def send_command(ctx):
# Set a specific propagation node once (config-level)
bot.set_propagation_node("<propagation_node_hash_here>")
# Send using configured delivery strategy
bot.send(
ctx.sender,
"This message will use direct delivery with propagation fallback as configured"
)
Узлы распространения полезны, когда прямая доставка невозможна или когда вы хотите обеспечить доставку сообщений через ячеистую сеть Reticulum.
Настройка повторных попыток¶
Configure automatic retry attempts for failed message deliveries via bot config:
from lxmfy import LXMFBot
bot = LXMFBot(name="ReliableBot")
bot = LXMFBot(
name="ReliableBot",
direct_delivery_retries=5, # Retry direct delivery up to 5 times
propagation_fallback_enabled=True
)
@bot.command(name="important", description="Send important message with retries")
def important_command(ctx):
bot.send(ctx.sender, "This is an important message")
@bot.command(name="normal", description="Send with default retries")
def normal_command(ctx):
# Default direct_delivery_retries is 3
bot.send(ctx.sender, "This message uses default retry settings")
Система повторных попыток:
Автоматически отслеживает попытки доставки для каждого получателя
Retries failed direct deliveries up to
direct_delivery_retriesСбрасывает счетчик повторных попыток при успешной доставке
Регистрирует попытки повтора и сбои для отладки