Основные понятия
В этом руководстве представлены основные концепции ErisPulse, которые помогут вам понять философию и архитектуру фреймворка.
Архитектура на основе событий
ErisPulse использует архитектуру на основе событий, где все взаимодействия передаются и обрабатываются через события.
Процесс событий
Пользователь отправляет сообщение
│
▼
Платформа получает
│
▼
Адаптер получает нативное событие платформы
│
▼
Преобразуется в стандартное событие OneBot12
│
▼
Отправляется в систему событий
│
▼
Распределяется по зарегистрированным обработчикам
│
▼
Модуль обрабатывает событие
│
▼
Ответ отправляется через адаптер
│
▼
Платформа отображает пользователю
Стандарт OneBot12
ErisPulse использует OneBot12 как основной стандарт событий. OneBot12 — это универсальный стандарт интерфейса для чат-ботов, определяющий единый формат событий.
Все адаптеры преобразуют платформенно-специфичные события в формат OneBot12, обеспечивая согласованность кода.
Основные компоненты
1. Объект SDK
SDK является единым точкой входа для всех функций, предоставляя доступ к основным компонентам.
from ErisPulse import sdk
# Доступ к основным модулям
sdk.storage # Система хранения
sdk.config # Система конфигурации
sdk.logger # Система логирования
sdk.adapter # Система адаптеров
sdk.module # Система модулей
sdk.router # Система маршрутизации
sdk.client # HTTP-клиент
sdk.lifecycle # Система жизненного цикла
2. Объект Event
Объект Event封装ует данные события и предоставляет удобные методы доступа.
@command("info")
async def info_handler(event):
# Получение информации о событии
event_id = event.get_id()
user_id = event.get_user_id()
platform = event.get_platform()
text = event.get_text()
# Отправка ответа
await event.reply(f"Пользователь: {user_id}, Платформа: {platform}")
3. Адаптеры
Адаптеры являются мостом между ErisPulse и внешними платформами.
Задачи:
- Получение нативных событий платформы
- Преобразование в формат OneBot12
- Отправка событий в формате OneBot12 на платформу
Примеры адаптеров:
- Адаптер Yunhu: коммуникация с платформой Yunhu
- Адаптер Telegram: коммуникация с Telegram Bot API
- Адаптер OneBot11: совместимость с OneBot11
- Адаптер Email: обработка отправки и получения электронной почты
4. Модули
Модули являются базовыми единицами расширения функциональности, позволяя:
- Регистрировать обработчики событий
- Реализовывать бизнес-логику
- Вызывать адаптеры для отправки сообщений
- Использовать сервисы, предоставляемые основными модулями
Механизм обнаружения модулей
ErisPulse использует importlib.metadata.entry_points для обнаружения установленных модулей. Модули объявляются в pyproject.toml с помощью entry points:
[project.entry-points."erispulse.module"]
MyModule = "my_package:Main"
При инициализации SDK происходит сканирование всех entry points группы erispulse.module, классы модулей регистрируются в ModuleManager, после чего они инициализируются в соответствии с зависимостями.
Минимально рабочий модуль
from ErisPulse.Core.Bases import BaseModule
from ErisPulse import sdk
class Main(BaseModule):
def __init__(self):
self.sdk = sdk
self.logger = sdk.logger.get_child("MyModule")
async def on_load(self, event):
self.logger.info("Модуль загружен")
async def on_unload(self, event):
self.logger.info("Модуль выгружен")
Жизненный цикл модуля
- Регистрация: SDK обнаруживает класс модуля и регистрирует его в менеджере
- Загрузка: Создается экземпляр модуля, вызывается
on_load(event)(event = {"module_name": "MyModule"}) - Выгрузка: Вызывается
on_unload(event), очищаются ресурсы
Стратегия загрузки
С помощью get_load_strategy() объявляется поведение загрузки модуля:
from ErisPulse.loaders import ModuleLoadStrategy
class Main(BaseModule):
@staticmethod
def get_load_strategy():
return ModuleLoadStrategy(
lazy_load=True, # Ленивая загрузка (по умолчанию True)
priority=0 # Приоритет загрузки, чем больше, тем раньше инициализируется
)
lazy_load=True(по умолчанию): Модуль инициализируется при первом обращении кsdk.MyModule, снижая время запускаlazy_load=False: Модуль инициализируется при запуске SDK, подходит для модулей, обрабатывающих события жизненного цикла или выполняющих фоновые задачиpriority: Модули с одинаковым приоритетом загружаются в порядке регистрации; чем больше значение, тем раньше инициализируется
Подробнее о механизме ленивой загрузки см. в Системе ленивой загрузки.
Типы событий
ErisPulse поддерживает 5 типов событий:
| Тип события | Декоратор | Описание |
|---|---|---|
| Событие сообщения | @message.on_message() |
Любое сообщение, отправленное пользователем (личные сообщения, группы) |
| Событие команды | @command("name") |
Сообщение, начинающееся с префикса команды (например, /hello) |
| Уведомление | @notice.on_friend_add() и др. |
Системные уведомления (добавление друзей, изменения в группе) |
| Запрос | @request.on_friend_request() и др. |
Запросы от пользователей (запросы на добавление в друзья, приглашения в группы) |
| Мета-событие | @meta.on_connect() и др. |
Системные события (подключение, отключение, heartbeat) |
Подробное описание и примеры использования каждого типа событий см. в Введение в обработку событий.
Описание основных модулей
Storage (Хранилище)
Хранилище на основе SQLite для постоянного хранения данных.
# Установка значения
sdk.storage.set("key", "value")
# Получение значения
value = sdk.storage.get("key", "default_value")
# Массовые операции
sdk.storage.set_multi({
"key1": "value1",
"key2": "value2"
})
# Транзакции
with sdk.storage.transaction():
sdk.storage.set("key1", "value1")
sdk.storage.set("key2", "value2")
Config (Конфигурация)
Управление конфигурационными файлами в формате TOML.
# Получение конфигурации
config = sdk.config.getConfig("MyModule", {})
# Установка конфигурации
sdk.config.setConfig("MyModule", {"key": "value"})
# Чтение вложенной конфигурации
value = sdk.config.getConfig("MyModule.subkey", "default")
Logger (Журнал)
Модульная система журналирования.
# Запись в журнал
sdk.logger.info("Это информационное сообщение")
sdk.logger.warning("Это предупреждение")
sdk.logger.error("Это ошибка")
# Получение дочернего логгера
child_logger = sdk.logger.get_child("submodule")
child_logger.info("Журнал подмодуля")
Синтаксис доступа по атрибутам
Помимо метода get_child(), можно использовать доступ по атрибутам для создания дочернего логгера, что является более компактным синтаксическим сахаром:
# Создание дочернего логгера через доступ по атрибутам
sdk.logger.mymodule.info("Сообщение модуля")
# Поддержка вложенного доступа
sdk.logger.mymodule.database.info("Сообщение базы данных")
Router (Маршрутизация)
Управление маршрутизацией HTTP и WebSocket, основано на FastAPI + Uvicorn. Поддерживает маршрутизацию с помощью декораторов, промежуточные слои, группы, ограничение скорости, CORS.
from ErisPulse.Core import HttpRequest
@sdk.router.get("MyModule", "/api")
async def handler(request: HttpRequest):
data = await request.json()
return {"status": "ok"}
Полный API маршрутизатора (WebSocket, промежуточные слои, ограничение скорости, CORS и др.) см. в Маршрутизаторе.
Client (Сетевой клиент)
Единый сетевой клиент, объединяющий HTTP-запросы, WebSocket-соединения, управление пулов, автоматические повторы, таймауты, статистику запросов и интеграцию с событиями жизненного цикла.
from ErisPulse.Core import client
# HTTP-запрос
resp = await client.get("https://api.example.com/users")
data = await resp.json()
# Запрос с повторами и таймаутом
resp = await client.get(url, timeout=30, max_retries=3)
# WebSocket-соединение
ws = await client.ws_connect("wss://example.com/ws")
async for text in ws.iter_text():
await ws.send_text(f"Эхо: {text}")
Полный API сетевого клиента см. в Сетевом клиенте.
DSL для отправки сообщений SendDSL
Адаптеры предоставляют интерфейс для отправки сообщений с цепочечным вызовом.
Базовая отправка
# Получение экземпляра адаптера
yunhu = sdk.adapter.get("yunhu")
# Отправка сообщения
await yunhu.Send.To("user", "U1001").Text("Привет")
# Указание отправляющего аккаунта
await yunhu.Send.Using("bot1").To("group", "G1001").Text("Сообщение в группе")
Цепочки модификаторов
# @пользователя
await yunhu.Send.To("group", "G1001").At("U2001").Text("@сообщение")
# Ответ на сообщение
await yunhu.Send.To("group", "G1001").Reply("msg123").Text("Ответ")
# @всех
await yunhu.Send.To("group", "G1001").AtAll().Text("Объявление")
Методы ответа в Event
Объект Event предоставляет удобные методы для отправки ответа:
@command("test")
async def test_handler(event):
# Простой текстовый ответ
await event.reply("Содержимое ответа")
# Отправка изображения
await event.reply("http://example.com/image.jpg", method="Image")
# Отправка голосового сообщения
await event.reply("http://example.com/voice.mp3", method="Voice")
Система ленивой загрузки
ErisPulse по умолчанию включает ленивую загрузку модулей, при которой модуль инициализируется только при первом обращении (например, sdk.MyModule), что значительно ускоряет запуск.
from ErisPulse.loaders import ModuleLoadStrategy
class Main(BaseModule):
@staticmethod
def get_load_strategy():
return ModuleLoadStrategy(
lazy_load=True, # Включить ленивую загрузку (по умолчанию)
priority=0 # Приоритет загрузки, чем больше, тем раньше инициализируется
)
Сценарии, требующие отключения ленивой загрузки (lazy_load=False):
- Модули, обрабатывающие события жизненного цикла (например,
core.init.complete) - Модули, запускающие фоновые задачи или сервисы
- Модули, требующие инициализации до других модулей
Подробнее о механизме ленивой загрузки и рекомендациях см. в Системе ленивой загрузки.
Далее
- Введение в обработку событий - изучите, как обрабатывать различные типы событий
- Примеры распространённых задач - освойте реализацию часто используемых функций