Создание ботов¶
Базовая структура¶
Минимальный бот 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 meme bot (fetches memes from an API)
lxmfy create --template meme my_meme_bot
Выполнение этих команд создает файл Python (например, my_echo_bot.py), который импортирует и запускает выбранный шаблон. Затем вы можете изменить сгенерированный файл или сам код шаблона (lxmfy/templates/...).
Пример сгенерированного файла (:code:`my_meme_bot.py`):
from lxmfy.templates import MemeBot
if __name__ == "__main__":
bot = MemeBot() # Creates an instance of the MemeBot template
# You can optionally override the default name:
# bot.bot.name = "My Awesome Meme 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, 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).
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 предоставляет бэкенды для хранения данных в форматах JSON и SQLite.
JSON: Простой, человекочитаемый формат. Подходит для небольших наборов данных. Настраивается с помощью
storage_type="json"иstorage_path="your_data_dir".SQLite: Более эффективен для больших наборов данных или частых записей. Настраивается с помощью
storage_type="sqlite"иstorage_path="your_db_file.db".
Вы можете получить доступ к интерфейсу хранилища через 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):
# Send through a specific propagation node
bot.send(
ctx.sender,
"This message was routed through a propagation node",
propagation_node="<propagation_node_hash_here>"
)
Узлы распространения полезны, когда прямая доставка невозможна или когда вы хотите обеспечить доставку сообщений через ячеистую сеть Reticulum.
Настройка повторных попыток¶
Настройте автоматические повторные попытки для неудачных доставок сообщений:
from lxmfy import LXMFBot
bot = LXMFBot(name="ReliableBot")
@bot.command(name="important", description="Send important message with retries")
def important_command(ctx):
# Send with custom retry count
bot.send(
ctx.sender,
"This is an important message that will retry up to 5 times on failure",
max_retries=5
)
@bot.command(name="normal", description="Send with default retries")
def normal_command(ctx):
# Default max_retries is 3
bot.send(ctx.sender, "This message uses default retry settings")
Система повторных попыток:
Автоматически отслеживает попытки доставки для каждого получателя
Повторяет неудачные доставки до указанного
max_retriesСбрасывает счетчик повторных попыток при успешной доставке
Регистрирует попытки повтора и сбои для отладки