Создание ботов

Базовая структура

Минимальный бот LXMFy включает в себя:

  1. Импорт LXMFBot.

  2. Создание экземпляра LXMFBot с желаемой конфигурацией.

  3. Определение команд или обработчиков событий.

  4. Запуск бота с помощью 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 можно предварительно рассчитать и использовать повторно для всех сообщений, отправляемых ботом.

Использование модулей (расширений)

Модули позволяют вам организовывать команды и прослушиватели событий в отдельные файлы (модули), сохраняя основной файл вашего бота в чистоте.

  1. Создайте каталог :code:`cogs` (или любое другое имя, которое вы указали для cogs_dir в BotConfig).

  2. Создайте файлы Python внутри каталога cogs (например, utility.py).

  3. Определите класс, который наследуется от lxmfy.Cog (необязательно, но рекомендуется) или является просто стандартным классом.

  4. Определите команды как методы внутри класса с помощью декоратора @Command.

  5. Создайте функцию :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).

Обработка событий

Вы можете регистрировать обработчики для различных событий бота с помощью декоратора @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 поддерживает криптографическую подпись и проверку сообщений для повышения безопасности. Когда эта функция включена, бот будет проверять, что входящие сообщения подписаны действительными идентификаторами RNS.

Configuration:

Включите проверку подписи в конфигурации вашего бота:

bot = LXMFBot(
    name="SecureBot",
    signature_verification_enabled=True,  # Enable signature verification
    require_message_signatures=False      # Set to True to reject unsigned messages
)

Как это работает:

  1. Исходящие сообщения: Когда проверка подписи включена, все исходящие сообщения автоматически подписываются с использованием идентификатора RNS бота.

  2. Входящие сообщения: Бот проверяет подписи на входящих сообщениях, используя идентификатор RNS отправителя.

  3. Неподписанные сообщения: Если установлено require_message_signatures=True, неподписанные сообщения отклоняются. В противном случае они принимаются, но регистрируются.

  4. Интеграция с разрешениями: Пользователи с разрешением BYPASS_SPAM могут обходить проверку подписи.

Управление через CLI:

Вы можете управлять настройками проверки подписи с помощью CLI:

# Test signature verification
lxmfy signatures test

# Enable signature verification
lxmfy signatures enable

# Disable signature verification
lxmfy signatures disable

Поля подписи:

Подписи хранятся в поле LXMF 0xFA. Процесс канонизации сообщения обеспечивает последовательную подпись путем детерминированного упорядочивания компонентов сообщения.