mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-16 01:40:15 +08:00
- Introduced LoadedCapability class to manage plugin capabilities. - Updated load_plugin function to discover and load capabilities alongside handlers. - Enhanced Peer class to handle remote provided capabilities during initialization. - Added tests for capability registration and invocation in legacy plugins. - Improved MessageChain and message component handling in legacy plugins. - Added comprehensive tests for legacy plugin integration and compatibility. - Updated protocol messages to include provided capabilities in initialization. - Enhanced top-level module imports to include capability-related functions.
120 lines
3.6 KiB
Python
120 lines
3.6 KiB
Python
"""v4 原生事件对象。
|
||
|
||
顶层 ``MessageEvent`` 保持精简,只承载 v4 运行时真正需要的基础能力。
|
||
旧版 ``AstrMessageEvent`` 的便捷方法与结果对象由
|
||
``astrbot_sdk.api.event`` 兼容层承接,而不是继续塞回顶层事件类型。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from collections.abc import Awaitable, Callable
|
||
from dataclasses import dataclass
|
||
from typing import TYPE_CHECKING, Any
|
||
|
||
from .protocol.descriptors import SessionRef
|
||
|
||
if TYPE_CHECKING:
|
||
from .context import Context
|
||
|
||
|
||
@dataclass(slots=True)
|
||
class PlainTextResult:
|
||
text: str
|
||
|
||
|
||
ReplyHandler = Callable[[str], Awaitable[None]]
|
||
|
||
|
||
class MessageEvent:
|
||
def __init__(
|
||
self,
|
||
*,
|
||
text: str = "",
|
||
user_id: str | None = None,
|
||
group_id: str | None = None,
|
||
platform: str | None = None,
|
||
session_id: str | None = None,
|
||
raw: dict[str, Any] | None = None,
|
||
context: "Context | None" = None,
|
||
reply_handler: ReplyHandler | None = None,
|
||
) -> None:
|
||
self.text = text
|
||
self.user_id = user_id
|
||
self.group_id = group_id
|
||
self.platform = platform
|
||
self.session_id = session_id or group_id or user_id or ""
|
||
self.raw = raw or {}
|
||
self._context = context
|
||
self._reply_handler = reply_handler
|
||
if self._reply_handler is None and context is not None:
|
||
self._reply_handler = lambda text: context.platform.send(
|
||
self.session_ref or self.session_id,
|
||
text,
|
||
)
|
||
|
||
@classmethod
|
||
def from_payload(
|
||
cls,
|
||
payload: dict[str, Any],
|
||
*,
|
||
context: "Context | None" = None,
|
||
reply_handler: ReplyHandler | None = None,
|
||
) -> "MessageEvent":
|
||
target_payload = payload.get("target")
|
||
session_id = payload.get("session_id")
|
||
platform = payload.get("platform")
|
||
if isinstance(target_payload, dict):
|
||
target = SessionRef.model_validate(target_payload)
|
||
session_id = session_id or target.session
|
||
platform = platform or target.platform
|
||
return cls(
|
||
text=str(payload.get("text", "")),
|
||
user_id=payload.get("user_id"),
|
||
group_id=payload.get("group_id"),
|
||
platform=platform,
|
||
session_id=session_id,
|
||
raw=payload,
|
||
context=context,
|
||
reply_handler=reply_handler,
|
||
)
|
||
|
||
def to_payload(self) -> dict[str, Any]:
|
||
payload = dict(self.raw)
|
||
payload.update(
|
||
{
|
||
"text": self.text,
|
||
"user_id": self.user_id,
|
||
"group_id": self.group_id,
|
||
"platform": self.platform,
|
||
"session_id": self.session_id,
|
||
}
|
||
)
|
||
if self.session_ref is not None:
|
||
payload["target"] = self.session_ref.to_payload()
|
||
return payload
|
||
|
||
@property
|
||
def session_ref(self) -> SessionRef | None:
|
||
if not self.session_id:
|
||
return None
|
||
return SessionRef(
|
||
conversation_id=self.session_id,
|
||
platform=self.platform,
|
||
raw=self.raw or None,
|
||
)
|
||
|
||
@property
|
||
def target(self) -> SessionRef | None:
|
||
return self.session_ref
|
||
|
||
async def reply(self, text: str) -> None:
|
||
if self._reply_handler is None:
|
||
raise RuntimeError("MessageEvent 未绑定 reply handler,无法 reply")
|
||
await self._reply_handler(text)
|
||
|
||
def bind_reply_handler(self, reply_handler: ReplyHandler) -> None:
|
||
self._reply_handler = reply_handler
|
||
|
||
def plain_result(self, text: str) -> PlainTextResult:
|
||
return PlainTextResult(text=text)
|