基本概念
このガイドでは、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 標準形式に変換
- 標準形式のイベントをプラットフォームに送信
例のアダプタ:
- Yunhu アダプタ:雲湖プラットフォームとの通信
- Telegram アダプタ:Telegram Bot API との通信
- OneBot11 アダプタ:OneBot11 互換アプリとの通信
- Email アダプタ:メールの送受信処理
4. モジュール
モジュールは機能拡張の基本単位であり、以下を実現できます:
- イベントハンドラの登録
- ビジネスロジックの実装
- アダプタを呼び出してメッセージを送信
- コアモジュールが提供するサービスの利用
モジュール発見メカニズム
ErisPulse は Python の importlib.metadata.entry_points を使用して、インストールされたモジュールを発見します。モジュールは pyproject.toml でエントリーポイントを宣言します:
[project.entry-points."erispulse.module"]
MyModule = "my_package:Main"
SDK の初期化時に、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() など |
システムレベルのイベント(接続、切断、ハートビート) |
各イベントの詳細な使用方法とコード例については、イベント処理の入門を参照してください。
核心モジュールの説明
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"Echo: {text}")
完全なネットワーククライアント API については、ネットワーククライアントを参照してください。
SendDSL メッセージ送信
アダプターは、チェーン呼び出し可能なメッセージ送信インターフェースを提供します。
基本的な送信
# アダプターのインスタンスを取得
yunhu = sdk.adapter.get("yunhu")
# メッセージを送信
await yunhu.Send.To("user", "U1001").Text("Hello")
# 送信アカウントを指定
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) - タイマーまたはバックグラウンドサービスを起動するモジュール
- 他のモジュールがロードされる前に初期化を完了させる必要があるモジュール
ラグドロードの詳細なメカニズムと注意事項については、ラグドロードシステムを参照してください。